<script type="importmap">

Baseline 已广泛支持

此功能已成熟,并可在许多设备和浏览器版本上运行。自 2023 年 3 月以来,它已在各种浏览器中可用。

<script> 元素的 type 属性的 importmap 值表示元素的主体包含一个导入映射。

导入映射是一个 JSON 对象,允许开发者控制浏览器在导入 JavaScript 模块时如何解析模块说明符。它提供了在 import 语句import() 操作符中用作模块说明符的文本与在解析说明符时将替换该文本的相应值之间的映射。JSON 对象必须符合导入映射 JSON 表示格式

导入映射用于解析静态和动态导入中的模块说明符,因此必须在任何使用映射中声明的说明符导入模块的 <script> 元素之前声明和处理。请注意,导入映射仅适用于导入到文档中的模块的 import 语句import() 操作符中的模块说明符;它不适用于 <script> 元素的 src 属性中指定的路径或导入到 Worker 或 Worklet 中的模块。

有关更多信息,请参阅 JavaScript 模块指南中的使用导入映射导入模块部分。

语法

html
<script type="importmap">
  // JSON object defining import
</script>

不得指定 srcasyncnomoduledefercrossoriginintegrityreferrerpolicy 属性。

异常

TypeError

导入映射定义不是 JSON 对象,importmap 键已定义但其值不是 JSON 对象,或者 scopes 键已定义但其值不是 JSON 对象。

对于导入映射 JSON 不符合导入映射模式的其他情况,浏览器会生成控制台警告。

描述

当导入 JavaScript 模块时,import 语句import() 操作符都有一个“模块说明符”,用于指示要导入的模块。浏览器必须能够将此说明符解析为绝对 URL 才能导入模块。

例如,以下语句从模块说明符 "https://example.com/shapes/circle.js"(一个绝对 URL)和模块说明符 "./modules/shapes/square.js"(一个相对于文档基本 URL 的路径)导入元素。

js
import { name as circleName } from "https://example.com/shapes/circle.js";
import { name as squareName, draw } from "./modules/shapes/square.js";

导入映射允许开发者在模块说明符中指定(几乎)任何他们想要的文本;映射提供了在解析模块说明符时将替换该文本的相应值。

裸模块

下面的导入映射定义了一个 imports 键,它具有一个带有 circlesquare 属性的“模块说明符映射”。

html
<script type="importmap">
  {
    "imports": {
      "circle": "https://example.com/shapes/circle.js",
      "square": "./modules/shapes/square.js"
    }
  }
</script>

有了这个导入映射,我们可以导入与上面相同的模块,但在我们的模块说明符中使用“裸模块”

js
import { name as circleName } from "circle";
import { name as squareName, draw } from "square";

映射路径前缀

模块说明符映射键也可以用于重新映射模块说明符中的路径前缀。请注意,在这种情况下,属性和映射路径都必须以尾部斜杠 (/) 结尾。

html
<script type="importmap">
  {
    "imports": {
      "shapes/": "./modules/shapes/",
      "other-shapes/": "https://example.com/modules/shapes/"
    }
  }
</script>

然后我们可以导入一个圆形模块,如所示。

js
import { name as circleName } from "shapes/circle.js";

模块说明符映射键中的路径

模块说明符键不必是单个单词名称(“裸名称”)。它们也可以包含或以路径分隔符结尾,或者可以是绝对 URL,或者是以 /./../ 开头的相对 URL 路径。

json
{
  "imports": {
    "modules/shapes/": "./modules/src/shapes/",
    "modules/square": "./modules/src/other/shapes/square.js",
    "https://example.com/modules/square.js": "./modules/src/other/shapes/square.js",
    "../modules/shapes/": "/modules/shapes/"
  }
}

如果模块说明符映射中有多个模块说明符键可能匹配,则会选择最具体的键(即,具有较长路径/值的键)。

模块说明符 ./foo/../js/app.js 将在匹配之前解析为 ./js/app.js。这意味着模块说明符键 ./js/app.js 将匹配该模块说明符,即使它们不完全相同。

范围化的模块说明符映射

您可以使用 scopes 键来提供仅在导入模块的脚本包含特定 URL 路径时才使用的映射。如果加载脚本的 URL 与提供的路径匹配,则将使用与范围关联的映射。这允许根据导入代码的不同使用不同版本的模块。

例如,下面的映射仅在加载模块的 URL 包含路径“/modules/custom-shapes/”时才使用范围化的映射。

html
<script type="importmap">
  {
    "imports": {
      "square": "./modules/shapes/square.js"
    },
    "scopes": {
      "/modules/custom-shapes/": {
        "square": "https://example.com/modules/shapes/square.js"
      }
    }
  }
</script>

如果多个范围与 referrer URL 匹配,则使用最具体的范围路径(名称最长的范围键名)。如果没有匹配的说明符,浏览器会回退到下一个最具体的范围路径,依此类推,最终回退到 imports 键中的模块说明符映射。

完整性元数据映射

您可以使用 integrity 键来提供模块完整性元数据的映射。这使您能够确保动态或静态导入模块的完整性。integrity 还允许您为顶级或预加载模块提供回退,以防它们尚未包含 integrity 属性。

映射键表示模块 URL,可以是绝对或相对(以 /./../ 开头)。映射值表示完整性元数据,与 integrity 属性值中使用的元数据相同。

例如,下面的映射为 square.js 模块(直接)及其裸说明符(通过 imports 键间接)定义了完整性元数据。

html
<script type="importmap">
  {
    "imports": {
      "square": "./modules/shapes/square.js"
    },
    "integrity": {
      "./modules/shapes/square.js": "sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"
    }
  }
</script>

合并多个导入映射

在内部,浏览器维护一个单一的全局导入映射表示。当一个文档中包含多个导入映射时,它们的内容在注册时会合并到全局导入映射中。

例如,考虑以下两个导入映射

html
<script type="importmap">
  {
    "imports": {
      "/app/": "./original-app/"
    }
  }
</script>
html
<script type="importmap">
  {
    "imports": {
      "/app/helper": "./helper/index.mjs"
    },
    "scopes": {
      "/js": {
        "/app/": "./js-app/"
      }
    }
  }
</script>

它们等效于以下单个导入映射

html
<script type="importmap">
  {
    "imports": {
      "/app/": "./original-app/",
      "/app/helper": "./helper/index.mjs"
    },
    "scopes": {
      "/js": {
        "/app/": "./js-app/"
      }
    }
  }
</script>

每个已注册映射中已提前解析的模块说明符将被丢弃。这些说明符的后续解析将提供与其先前解析相同的结果。

例如,如果模块说明符 /app/helper.js 已解析,则以下新导入映射

html
<script type="importmap">
  {
    "imports": {
      "/app/helper.js": "./helper/index.mjs",
      "lodash": "/node_modules/lodash-es/lodash.js"
    }
  }
</script>

将等效于

html
<script type="importmap">
  {
    "imports": {
      "lodash": "/node_modules/lodash-es/lodash.js"
    }
  }
</script>

/app/helper.js 规则被忽略,未并入映射。

同样,已注册映射中已映射到全局映射中 URL 的模块说明符将被丢弃;它们的先前映射优先。

例如,以下两个导入映射

html
<script type="importmap">
  {
    "imports": {
      "/app/helper": "./helper/index.mjs",
      "lodash": "/node_modules/lodash-es/lodash.js"
    }
  }
</script>
html
<script type="importmap">
  {
    "imports": {
      "/app/helper": "./main/helper/index.mjs"
    }
  }
</script>

等效于以下单个导入映射

html
<script type="importmap">
  {
    "imports": {
      "/app/helper": "./helper/index.mjs",
      "lodash": "/node_modules/lodash-es/lodash.js"
    }
  }
</script>

/app/helper/ 规则已从第二个映射中删除。

注意:在不支持的浏览器中(查看兼容性数据),可以使用 polyfill 来避免与模块解析相关的问题。

导入映射 JSON 表示

以下是导入映射 JSON 表示的“正式”定义。

导入映射必须是有效的 JSON 对象,可以定义任何可选键 importsscopesintegrity。每个键的值必须是一个对象,可以为空。

imports 可选

该值是一个模块说明符映射,它提供了可能出现在 import 语句或 import() 操作符中的模块说明符文本与在解析说明符时将替换该文本的文本之间的映射。

这是回退映射,如果在 scopes 路径 URL 中没有匹配项,或者在匹配的 scopes 路径中的模块说明符映射不包含与模块说明符匹配的键时,将搜索此映射以查找匹配的模块说明符。

<模块说明符映射>

“模块说明符映射”是一个有效的 JSON 对象,其中是在导入模块时可能存在于模块说明符中的文本,相应的是在将模块说明符解析为地址时将替换此文本的 URL 或路径。

模块说明符映射 JSON 对象有以下要求

  • 任何键都不得为空。
  • 所有值都必须是字符串,定义一个有效的绝对 URL 或一个以 /./../ 开头的有效 URL 字符串。
  • 如果键以 / 结尾,则相应的值也必须以 / 结尾。带有尾部 / 的键可以用作映射(或重新映射)模块地址的前缀。
  • 对象属性的顺序无关紧要:如果多个键可以匹配模块说明符,则使用最具体的键(换句话说,说明符“olive/branch/”将先于“olive/”匹配)。
integrity 可选

定义一个有效的 JSON 对象,其中是包含有效绝对或相对 URL(以 /./../ 开头)的字符串,相应的是有效的完整性元数据

如果导入或预加载模块的脚本的 URL 与 integrity 对象中的键匹配,则相应的完整性元数据将应用于脚本的获取选项,除非它们已附加完整性元数据。

scopes 可选

范围定义了特定路径的模块说明符映射,允许映射的选择取决于导入模块的代码路径。

范围对象是一个有效的 JSON 对象,其中每个属性都是一个 <scope key>(一个 URL 路径),其相应的值是一个 <module specifier map>

如果导入模块的脚本的 URL 与 <scope key> 路径匹配,则首先检查与该键关联的 <module specifier map> 值以查找匹配的说明符。如果存在多个匹配的范围键,则首先检查与最具体/嵌套的范围路径关联的值以查找匹配的模块说明符。如果在任何匹配的范围模块说明符映射中没有匹配的模块说明符键,则使用 imports 中的回退模块说明符映射。

请注意,范围不会改变地址的解析方式;相对地址始终解析为导入映射基本 URL。

规范

规范
HTML
# import-map

浏览器兼容性

另见