作者选择了 Creative Commons以作为 Write for Donations计划的一部分获得捐赠。
介绍
外部库可以为新的 JavaScript 项目增加复杂性. 要安装和使用外部代码库,您需要一个构建工具,可以分析代码并将您导入的库合并到最终格式。
例如,你可能只需要一个库在你的应用程序的一部分,大多数用户可能永远不会需要的应用程序的一部分,比如一个管理页面,但默认情况下,大多数构建系统会将所有代码包装成一个大文件,用户将加载代码,无论他们是否需要执行它。
构建工具是开发经验的重要组成部分,但是一个叫做"导入地图" 的光谱将允许您在没有构建工具的情况下将外部代码导入您的项目,并且只有在运行时需要时才会加载代码. 导入地图不会完全取代执行许多其他有价值动作的构建工具,比如构建样式表和处理图像,但它们会允许您快速并方便地使用本地浏览器功能来拖曳新的JavaScript应用程序.
在此教程中,您会使用导入地图和JavaScript模块来导入代码而无需构建工具. 您将创建一个基本应用程序, 显示一个消息, 您将创建一个导入地图, 它会告诉你的浏览器在哪里 定位外部代码。 接下来,您将把所导入的代码整合到您的JavaScript中,并使用第三方代码而无需在本地下载代码或通过构建步骤运行. 最后,你会了解当前执行导入地图许多方面的工具,并研究所有现代浏览器.
前提条件
- 联合国 您需要一个运行 [Node.js] (https://nodejs.org/en/about/) 的开发环境 。 这个教程在Node.js版本14.17.1和npm版本6.14.23上进行了测试. 要在 macOS 或 Ubuntu 18.04 上安装此功能,请遵循 [如何在 macOS (https://andsky.com/tech/tutorials/how-to-install-node-js-and-create-a-local-development-environment-on-macos) 上安装节点并创建本地开发环境(https://andsky.com/tech/tutorials/how-to-install-node-js-on-ubuntu-18-04) 或使用 [如何在 Ubuntu 18.04 (https://andsky.com/tech/tutorials/how-to-install-node-js-on-ubuntu-18-04 上安装节点.js] 的 PPA** 部分中的步骤。
- 联合国 您还需要关于 JavaScript 的基本知识, 您可以在 [How To Code in JavaScript (https://www.digitalocean.com/community/tutorial_series/how-to-code-in-javascript) (JavaScript) (HTML (https://www.digitalocean.com/community/tutorial_series/how-to-build-a-website-with-html) 和 [CSS (https://www.digitalocean.com/community/tutorial_series/how-to-style-html-with-css ) 中找到这些知识. HTML和CSS的好资源是Mozilla开发者网络. .
第1步:创建一个HTML页面并插入JavaScript
在此步骤中,您将创建一个HTML页面,使用JavaScript进行动态活动,并启动本地开发服务器来跟踪您的更改。
要开始,在新目录中,创建一个空白的HTML文档。
在文本编辑器中打开名为index.html的文件:
1nano index.html
在文件内部,添加一个短,空白的HTML页面:
1[label index.html]
2<!DOCTYPE html>
3<html lang="en-US">
4 <head>
5 <meta charset="utf-8">
6 <meta http-equiv="X-UA-Compatible" content="IE=edge">
7 <title>Hello World</title>
8 <meta name="viewport" content="width=device-width, initial-scale=1">
9 </head>
10 <body>
11 </body>
12</html>
本文档有几个标准的 <meta>
标签和一个空的 <body>
元素。
然后添加一个<script>
标签. 脚本标签的src
属性将是一个新的JavaScript文件,您即将创建的名为hello.js
:
1[label index.html]
2<!DOCTYPE html>
3<html lang="en-US">
4<head>
5 <meta charset="utf-8">
6 <meta http-equiv="X-UA-Compatible" content="IE=edge">
7 <title>Hello World</title>
8 <meta name="viewport" content="width=device-width, initial-scale=1">
9 <script defer src="./hello.js"></script>
10</head>
11<body>
12</body>
请注意,您正在向 <script>
标签添加一个 defer 属性,这会延迟脚本标签的执行,直到文档被解析后。
接下来,在同一个目录中创建一个名为hello.js
的JavaScript文件,如index.html
:
1nano hello.js
在文件中,写一些JavaScript来创建一个新的文本元素,上面写着Hello, World
:
1[label hello.js]
2const el = document.createElement('h1');
3const words = "Hello, World!"
4const text = document.createTextNode(words);
5el.appendChild(text);
6
7document.body.appendChild(el);
现在你有你的脚本,你可以在浏览器中打开index.html
文件. 在与你的index.html
文件相同的目录中,运行npx serve
。这将运行本地的 serve
包,而不会下载到你的node_modules
。
1npx serve
该命令会询问您是否要安装一个软件包。键入y
以同意:
1Need to install the following packages:
2 serve
3Ok to proceed? (y) y
当你运行命令时,你会看到一些这样的输出:
1npx: installed 88 in 15.187s
2
3 ┌────────────────────────────────────────┐
4 │ │
5 │ Serving! │
6 │ │
7 │ Local: http://localhost:5000 │
8 │ │
9 │ Copied local address to clipboard! │
10 │ │
11 └────────────────────────────────────────┘
当你打开你的网页浏览器到 http://localhost:5000
,你会看到你的代码. 您可以离开服务器运行在一个单独的标签或窗口或关闭它与 CTRL+C
在预览你的代码后。
现在您正在浏览器中显示一个基本页面,但您尚未能够利用第三方代码和JavaScript套件。在下一步,您将动态导入代码并导入函数到脚本中,而无需构建工具。
步骤 2 — 使用 ES6 模块编写 Hello World 脚本
在此步骤中,您将编写使用外部包的代码. 您将修改代码以使用 ES 导入导入 JavaScript 代码. 最后,您将使用模块
类型将代码加载到您的浏览器中,以便浏览器能够动态加载代码。
首先,打开hello.js
:
1nano hello.js
你要从 lodash
导入一些代码,以动态地改变你的文本。
然后在文件的顶部,从lodash
导入 startCase
函数,使用标准ES6的导入
语法:
1[label hello.js]
2import startCase from '@lodash/startCase';
3
4const el = document.createElement('h1');
5const words = "hello, world";
6const text = document.createTextNode(words);
7el.appendChild(text);
8
9document.body.appendChild(el);
最后,用words
变量作为document.createTextNode
中的参数调用startCase
:
1[label hello.js]
2import startCase from '@lodash/startCase';
3
4const el = document.createElement('h1');
5const words = "hello, world";
6const text = document.createTextNode(startCase(words));
7el.appendChild(text);
8
9document.body.appendChild(el);
如果你关闭了你的网页服务器,打开一个新的终端窗口或卡,然后运行npx服务器
重新启动服务器,然后在网页浏览器中导航到http://localhost:5000
查看更改。
当您在浏览器中预览代码时,请 打开开发者控制台。
1[secondary_label Output]
2Uncaught SyntaxError: Cannot use import statement outside a module
由于代码使用导入
语句,您将需要修改index.html
内部的<script>
标签,以处理现在在多个文件之间分割的JavaScript。
关闭hello.js
并打开index.html
:
1nano index.html
若要将脚本运行为模块,请在<script>
标签上的type
属性值更改为module
:
1[label hello.js]
2<!DOCTYPE html>
3<html lang="en-US">
4<head>
5 <meta charset="utf-8">
6 <meta http-equiv="X-UA-Compatible" content="IE=edge">
7 <title>Hello World</title>
8 <meta name="viewport" content="width=device-width, initial-scale=1">
9 <script type="module" src="./hello.js"></script>
10</head>
11<body>
12</body>
13</html>
注意,您还删除了推迟
属性,JavaScript模块将不会执行,直到页面被解析。
打开浏览器,你仍然会看到一个错误`:
1[secondary_label Output]
2Uncaught TypeError: Failed to resolve module specifier "@lodash/startCase". Relative references must start with either "/", "./", or "../"
现在问题不在于导入
陈述,问题在于浏览器不知道导入
陈述的含义,它正在等待在 Web 服务器上找到代码,因此它正在寻找与当前文件相关的文件,要解决这个问题,你需要一个名为导入地图
的新工具。
在此步骤中,您学会了如何修改 JavaScript 代码以使用 ES 导入来加载外部库,您还修改了 HTML script
标签以处理 JavaScript 模块。
在下一步中,您将告诉浏览器如何使用导入地图
来找到代码。
步骤 3 — 使用导入地图加载外部代码
在此步骤中,您将学习如何创建导入地图,以告诉您的浏览器在哪里找到外部代码。
导入地图
是一个JavaScript对象,其中密钥是导入的名称(‘@lodash/startCase’),值是代码的位置。
在index.html
中添加一个新的script
标签,其中包含importmap
的类型
。在script
标签中,创建一个 JavaScript 对象,其中包含一个imports
的密钥。
1[label hello.js]
2<!DOCTYPE html>
3<html lang="en-US">
4<head>
5 <meta charset="utf-8">
6 <meta http-equiv="X-UA-Compatible" content="IE=edge">
7 <title>Hello World</title>
8 <meta name="viewport" content="width=device-width, initial-scale=1">
9 <script type="importmap">
10 {
11 "imports": {
12 }
13 }
14 </script>
15 <script type="module" src="./hello.js"></script>
16</head>
17<body>
18</body>
19</html>
请确保您不会在对象中添加任何追踪符号,浏览器不会知道如何处理它们。
现在你有你的基本对象,你可以添加你的代码的位置. 导入地图的结构将是这样的:
1{
2 "imports": {
3 "nameOfImport": "locationOfCode",
4 "nameOfSecondImport": "secondLocation"
5 }
6}
您已经知道您的导入名称@lodash/startCase
,但现在您需要找到导入地图指向的位置。
一个很好的资源是 unpkg。 Unpkg 是一个内容交付网络(CDN)为任何包在 npm
. 如果你可以 npm安装
一个包,你应该能够通过 unpkg 加载它. Unpkg 还包括一个浏览选项,可以帮助你找到你需要的特定文件。
要找到 startCase
代码,请在浏览器中打开 https://unpkg.com/browse/[email protected]/ 请注意 URL 中的 browse
字。这为您提供了图形的方式来浏览目录,但您不应该将路径添加到您的导入地图,因为它是 HTML 页面而不是原始 JavaScript 文件。
另外,请注意,您正在浏览lodash-es
,而不是lodash
。这就是以 ES 模块形式导出的lodash
库,这就是您在这种情况下所需要的。
浏览代码,你会注意到有一个名为 startCase.js
的文件。这个代码导入其他函数,并使用它们将每个单词的第一个字母转换为上一个字母:
1import createCompounder from './_createCompounder.js';
2import upperFirst from './upperFirst.js';
3
4/**
5 * Converts `string` to
6 * [start case](https://en.wikipedia.org/wiki/Letter_case#Stylistic_or_specialised_usage).
7 *
8 * @static
9 * @memberOf _
10 * @since 3.1.0
11 * @category String
12 * @param {string} [string=''] The string to convert.
13 * @returns {string} Returns the start cased string.
14 * @example
15 *
16 * _.startCase('--foo-bar--');
17 * // => 'Foo Bar'
18 *
19 * _.startCase('fooBar');
20 * // => 'Foo Bar'
21 *
22 * _.startCase('__FOO_BAR__');
23 * // => 'FOO BAR'
24 */
25var startCase = createCompounder(function(result, word, index) {
26 return result + (index ? ' ' : '') + upperFirst(word);
27});
28
29export default startCase;
浏览器将遵循导入
声明并导入所需的每个文件。
现在你已经有了导入地图的位置,更新文件导入地图以新的URL。在index.html
内,添加@lodash/startCase
和URL。
1[label index.html]
2<!DOCTYPE html>
3<html lang="en-US">
4<head>
5 <meta charset="utf-8">
6 <meta http-equiv="X-UA-Compatible" content="IE=edge">
7 <title>Hello World</title>
8 <meta name="viewport" content="width=device-width, initial-scale=1">
9 <script type="importmap">
10 {
11 "imports": {
12 "@lodash/startCase": "https://unpkg.com/[email protected]/startCase.js"
13 }
14 }
15 </script>
16 <script type="module" src="./hello.js"></script>
17</head>
18<body>
19</body>
20</html>
保存文件. 更新您的浏览器,你会看到 Hello World 。
<$>[注] 注: 导入地图尚未得到广泛支持。在最新版本的 Edge 或 Chrome 中打开代码,或查看最新版本的 支持的浏览器。
您的浏览器显示Hello World
,但现在发生了更有趣的事情。在浏览器中打开 浏览器控制台,选择 Inspect Elements ,然后切换到 ** 网络** 卡。
在打开网络
选项卡后,刷新页面,你会看到浏览器正在动态地加载代码。
更重要的是,请注意,所有的代码都被懒惰地加载,这意味着浏览器不会导入任何代码,直到具体需要。例如,即使startCase
位于导入地图中,并且导入地图在hello.js
脚本之前被定义,但直到hello.js
下载并导入代码后,它才被加载。
如果您要在导入地图中添加其他条目,浏览器就不会加载它们,因为它们从未被导入到代码中。
一个主要的问题是,导入地图尚未得到所有浏览器的完全支持,即使它们受支持,一些用户也可能无法使用受支持的浏览器,幸运的是,有不同的项目使用导入地图语法,同时添加完整的浏览器支持。
在此步骤中,您创建了一个导入地图,您还了解了如何导入模块代码,以及该代码将如何懒惰地加载到浏览器中。
步骤 4 – 使用 SystemJS 构建跨浏览器支持
在此步骤中,您将在使用 SystemJS 的所有浏览器中使用导入地图。您将导出代码作为 SystemJS 构建,以及如何设置导入地图类型以使用 SystemJS 格式。
导入地图将从应用程序中删除许多复杂的构建步骤,但尚未得到广泛的支持。
幸运的是,有一个名为SystemJS的项目可以使用创建导入地图来提供跨浏览器支持,并使用各种包构建。
lodash 图书馆方便,因为它是以 ES 格式编译的,但大多数图书馆并非如此。 许多图书馆是以其他格式导出的。 其中最常见的是 Universal Module Definition 或 UMD。
一个主要的区别是,与ES导入不同,UMD构建通常将所有代码合并到一个文件中。
若要更新您的项目以使用 SystemJS 和 UMD 构建的 lodash,请先打开hello.js
:
1nano hello.js
更改导入
声明以直接从lodash
导入startCase
函数。
1[label hello.js]
2import { startCase } from 'lodash';
3
4const el = document.createElement('h1');
5const words = "hello, world";
6const text = document.createTextNode(startCase(words));
7el.appendChild(text);
8
9document.body.appendChild(el);
保存并关闭文件。
接下来,要将文件构建为 SystemJS 构建,您需要一个简单的构建步骤. 您可以使用另一个构建工具,例如 webpack,但在这个示例中,您将使用 rollup
。
首先,初始化项目以创建一个 package.json
文件. 添加 -y
旗帜以接受所有默认值:
1npm init -y
运行命令后,您将看到成功的输出:
1{
2 "name": "hello",
3 "version": "1.0.0",
4 "description": "",
5 "main": "index.js",
6 "devDependencies": {},
7 "scripts": {
8 "test": "echo \"Error: no test specified\" && exit 1"
9 },
10 "keywords": [],
11 "author": "",
12 "license": "ISC",
13 "homepage": ""
14}
注意:您的输出可能略有不同,取决于您正在使用的 npm
版本。
接下来,安装rollup
作为一个devDepenceny
:
1npm install --save-dev rollup
过了一会儿,你会看到一个成功消息:
1+ rollup@2.56.2
2added 1 package from 1 contributor and audited 2 packages in 6.85s
3found 0 vulnerabilities
接下来,创建一个简单的构建配置,打开一个名为rollup.config.js的新文件:
1nano rollup.config.js
然后添加一个配置,将以 SystemJS 格式输出代码:
1[label rollup.config.js]
2export default {
3 external: ["lodash"],
4 input: ["hello.js"],
5 output: [
6 {
7 dir: "public",
8 format: "system",
9 sourcemap: true
10 }
11 ]
12};
外部
密钥告诉 rollup 不要在最终构建中包含任何 lodash 代码,当导入时 SystemJS 会动态地加载该代码。
输入
是根文件的位置,而输出
则告诉 rollup 把最终代码放在哪里,以及它应该使用的格式,在这种情况下是系统
。
保存并关闭文件。
现在你有一个构建步骤,你需要添加一个任务来运行它。
1nano package.json
在脚本
对象中,添加一个名为构建
的脚本,该脚本将运行rollup -c
。
1[label package.json]
2{
3 "name": "hello",
4 "version": "1.0.0",
5 "description": "",
6 "main": "hello.js",
7 "devDependencies": {
8 "rollup": "^2.56.2"
9 },
10 "scripts": {
11 "build": "rollup -c"
12 },
13 "keywords": [],
14 "author": "",
15 "license": "ISC",
16 "homepage": ""
17}
保存和关闭文件,然后运行构建
命令:
1npm run build
命令将短暂运行,然后你会看到一个成功消息:
1> rollup -c
2
3hello.js → public...
4created public in 21ms
您还会看到一个名为公共
的新目录,其中包含内置的文件. 如果您打开公共/hello.js
,您将看到您的项目以系统格式编译。
1nano public/hello.js
该文件将看起来像这样. 它类似于hello.js
与周围的System.register
方法。 此外,lodash
位于一个阵列中. 这将告诉 SystemJS 在运行时间内加载外部库。
1[label public/hello.js]
2System.register(['lodash'], function () {
3 'use strict';
4 var startCase;
5 return {
6 setters: [function (module) {
7 startCase = module.startCase;
8 }],
9 execute: function () {
10
11 const el = document.createElement('h1');
12 const words = "hello, world";
13 const text = document.createTextNode(startCase(words));
14 el.appendChild(text);
15
16 document.body.appendChild(el);
17
18 }
19 };
20});
21//# sourceMappingURL=hello.js.map
保存并关闭文件。
最后一步是更新您的index.html以处理新文件:
打开index.html
1nano index.html
首先,您需要导入 SystemJS 代码,使用一个常规的 <script>
标签,其中有 `src' 属性指向 CDN 发行版。
将<script>
标签放在导入地图的右下方:
1[label index.html]
2<!DOCTYPE html>
3<html lang="en-US">
4<head>
5 <meta charset="utf-8">
6 <meta http-equiv="X-UA-Compatible" content="IE=edge">
7 <title>Hello World</title>
8 <meta name="viewport" content="width=device-width, initial-scale=1">
9 <script type="importmap">
10 {
11 "imports": {
12 "@lodash/startCase": "https://unpkg.com/[email protected]/startCase.js
13 }
14 }
15 </script>
16 <script src="https://cdn.jsdelivr.net/npm/systemjs/dist/system.js"></script>
17 <script type="module" src="./hello.js"></script>
18</head>
19<body>
20</body>
21</html>
此格式类似于您在步骤 3 中完成的格式,但有三个更改:
- 更新导入地图
类型
。 * 更新引用lodash
。 * 添加引用hello.js
脚本。
首先,更新类型
。由于这不是导入地图的本体浏览器版本,而是systemjs
版本,请将类型更改为systemjs-importmap
:
1[label index.html]
2<!DOCTYPE html>
3<html lang="en-US">
4<head>
5 <meta charset="utf-8">
6 <meta http-equiv="X-UA-Compatible" content="IE=edge">
7 <title>Hello World</title>
8 <meta name="viewport" content="width=device-width, initial-scale=1">
9 <script type="systemjs-importmap">
10 {
11 "imports": {
12 "@lodash/startCase": "https://unpkg.com/[email protected]/startCase.js
13 }
14 }
15 </script>
16 <script src="https://cdn.jsdelivr.net/npm/systemjs/dist/system.js"></script>
17 <script type="module" src="./hello.js"></script>
18</head>
19<body>
20</body>
21</html>
接下来,更新参照,将@lodash/startCase
更改为lodash
。您将导入完整的库,然后更改 UMD 构建的位置,以 unpkg。
然后为你好
添加一个新的条目,并将其指向公共
目录中的编译版本:
1[label index.html]
2...
3 <meta name="viewport" content="width=device-width, initial-scale=1">
4 <script type="systemjs-importmap">
5 {
6 "imports": {
7 "hello": "./public/hello.js",
8 "lodash": "https://unpkg.com/[email protected]/lodash.js"
9 }
10 }
11 </script>
12...
现在你正在导入systemJS
,并更新了导入地图,剩下的只是加载模块。
将模块的script
标签上的type
属性更改为systemjs-module
。然后将src
更改为import:hello
。
1[label hello.js]
2...
3 <script type="systemjs-importmap">
4 {
5 "imports": {
6 "hello": "./public/hello.js",
7 "lodash": "https://unpkg.com/[email protected]/lodash.js"
8 }
9 }
10 </script>
11 <script src="https://cdn.jsdelivr.net/npm/systemjs/dist/system.js"></script>
12 <script type="systemjs-module" src="import:hello"></script>
13</head>
14...
保存并关闭文件。
当你这样做时,浏览器会更新,你会看到 Hello World 。
与本地导入地图不同,这将在任何浏览器中工作. 以下是FireFox的结果:
如果你看看网络
选项卡,你会看到,与导入地图一样,代码按需要懒惰地加载:
在此步骤中,您在使用 SystemJS 的浏览器中使用了导入地图,您更改了脚本以使用 lodash 的 UMD 构建,创建了一个 rollup 构建以在系统
格式中输出代码,并更改了导入地图和模块类型以与 SystemJS 工作
结论
在本教程中,您使用了导入地图来动态加载JavaScript代码. 您渲染了一个应用程序,在没有任何构建步骤的情况下动态加载外部库. 然后,您创建了一个构建过程,以在SystemJS格式中生成代码,以便您可以在所有浏览器中使用导入地图。
导入地图为您提供了开始将大型项目分解为较小的独立片段的机会,称为 microfrontends.您也不需要像本教程中所学的那样限制自己对静态定义的地图;您还可以创建 动态导入地图可以从其他脚本中加载。
新的功能正在进行中,您可以在 官方规格上跟踪它们。