「这是我参与11月更文挑战的第22天,活动详情查看:2021最后一次更文挑战」
如何在浏览器中引用 ESM?
大家好,我是山月。Bundless 越来越流行,特别是由于 Vite 的引入。
而 ESM 是 Bundless 的基础,了解 ESM 非常必要,今天这篇文章由我对如何在浏览器中引用 ESM 做一个简单的科普。
Native Import: Import from URL
通过 script[type=module]
,可直接在浏览器中使用原生 ESM
。
这也使得前端不打包 (Bundless
) 成为可能。
<script type="module">
import lodash from 'https://cdn.skypack.dev/lodash'
</script>
复制代码
由于前端跑在浏览器中,因此它也只能从 URL 中引入 Package
- 绝对路径:
https://cdn.sykpack.dev/lodash
- 相对路径:
./lib.js
现在打开浏览器控制台,把以下代码粘贴在控制台中。由于 http import
的引入,你发现你调试 lodash
此列工具库更加方便了。
> lodash = await import('https://cdn.skypack.dev/lodash')
> lodash.get({ a: 3 }, 'a')
复制代码
ImportMap
但 Http Import
每次都需要输入完全的 URL,相对以前的裸导入 (bare import specifiers
),很不太方便,如下例:
import lodash from 'lodash'
复制代码
它不同于 Node.JS
可以依赖系统文件系统,层层寻找 node_modules
/home/app/packages/project-a/node_modules/lodash/index.js
/home/app/packages/node_modules/lodash/index.js
/home/app/node_modules/lodash/index.js
/home/node_modules/lodash/index.js
复制代码
在 ESM 中,可通过 importmap
使得裸导入可正常工作:
<script type="importmap">
{
"imports": {
"lodash": "https://cdn.skypack.dev/lodash",
"ms": "https://cdn.skypack.dev/ms"
}
}
</script>
复制代码
此时可与以前同样的方式进行模块导入
import lodash from 'lodash'
import("lodash").then(_ => ...)
复制代码
那么通过裸导入如何导入子路径呢?
<script type="importmap">
{
"imports": {
"lodash": "https://cdn.skypack.dev/lodash",
"lodash/": "https://cdn.skypack.dev/lodash/"
}
}
</script>
<script type="module">
import get from 'lodash/get.js'
</script>
复制代码
Import Assertion
通过 script[type=module]
,不仅可引入 Javascript 资源,甚至可以引入 JSON/CSS,示例如下
严格来说,不算是 ESM,毕竟它连 ES 都不是,更谈不上 ECMAScript Module 了。
<script type="module">
import data from './data.json' assert { type: 'json' }
console.log(data)
</script>
复制代码