Skip to content

一文看懂 <script type="importmap">

简单介绍

当我们在网页上写 JavaScript 代码的时候,经常需要用到别人已经写好的代码块,也就是所谓的 "模块"。例如,我们可能需要用到 Lodash 这个工具库,或者 React 这个 UI 库。但问题来了,我们怎么告诉浏览器去哪里找这些代码呢?这就是 <script type="importmap"> 的作用。

首先,我们来看一下 <script type="importmap"> 是怎么写的:

html
<script type="importmap">
{
  "imports": {
    "lodash": "/path/to/lodash.js",
    "react": "/url/to/react.js"
  },
  "scopes": {
    "/my/page/": {
      "lodash": "/different/path/to/lodash.js"
    }
  }
}
</script>

你可以看到,<script type="importmap"> 是一个 JSON 数据格式,主要包括两部分:importsscopes。这两部分的作用分别是 "告诉浏览器去哪里找到我们需要的模块" 和 "告诉浏览器在不同的地方可能需要用到不同版本的模块"。

明白什么是裸模块

在 JavaScript 里,当我们需要引用一个模块时,通常需要提供模块的具体位置,像这样:import { something } from '/path/to/my-module.js'。但有时候,我们更希望像这样直接用模块的名字来引用它:import { something } from 'my-module'。这种直接用模块名字来引用的方式,就被称为 "裸模块"。

但问题是,如果没有 <script type="importmap">,浏览器并不知道 'my-module' 到底在哪里。这就像你告诉朋友去找一个叫 "小明" 的人,但你并没有告诉他 "小明" 在哪里,你的朋友肯定会很困惑。

而有了 <script type="importmap">,我们就可以告诉浏览器 "小明" 在哪里了:

html
<script type="importmap">
{
  "imports": {
    "my-module": "/url/to/my-module.js"
  }
}
</script>

明白什么是映射路径前缀

有时候,我们可能需要引入的不只是一个模块,而是一个文件夹里的很多模块。这个时候,我们可以用 <script type="importmap"> 来定义一个共同的路径前缀:

html
<script type="importmap">
{
  "imports": {
    "my-modules/": "/url/to/my-modules/"
  }
}
</script>

然后,当我们需要引入这个文件夹下的任何一个模块时,就可以直接用这个前缀:

javascript
import { something } from 'my-modules/module1';

明白什么是作用域模块标识符映射

有时候,我们在不同的页面可能需要用到不同版本的同一个模块。这时,我们就可以用 <script type="importmap">scopes 部分来定义这个规则:

html
<script type="importmap">
{
  "imports": {
    "lodash": "/path/to/lodash.js"
  },
  "scopes": {
    "/my/page/": {
      "lodash": "/different/path/to/lodash.js"
    }
  }
}
</script>

这就像我们告诉浏览器,在 "/my/page/" 这个页面,当我们说 "lodash" 的时候,其实是指 "/different/path/to/lodash.js"。

注意浏览器兼容性问题

虽然 <script type="importmap"> 很方便,但是并不是所有的浏览器都支持。例如,截止到2023年,Firefox 和 Safari 还不支持这个特性。但别担心,对于这些不支持的浏览器,我们可以用一些别的工具(比如 es-module-shims)来达到同样的效果。

总的来说,<script type="importmap"> 就像是一个 "导航仪",帮助浏览器找到我们需要的 JavaScript 模块。只要学会了怎么使用它,写 JavaScript 代码就会变得更加轻松。