importmap 是浏览器原生支持的模块映射机制,Chrome 89+、Firefox 109+、Safari 16.4+ 原生支持,通过 <script type="importmap"> 声明 JSON 映射,实现裸模块名到 URL 的重写,无需构建工具。
importmap 是浏览器原生支持的模块映射机制,能让你用简洁的模块名(比如 "lodash")代替冗长的 URL(比如 "https://cdn.jsdelivr.net/npm/[email protected]/index.js"),且无需构建工具。但它目前只在 Chromium 94+、Firefox 109+ 和 Safari 16.4+ 中可用,**不支持动态更新或运行时修改**。
importmap 块必须是 <script type="importmap">,放在 <head> 中(执行顺序敏感,要早于任何 import 脚本)。内容是标准 JSON,顶层只有 "imports" 字段("scopes" 可选但更复杂):
{ "imports": { "react": "https://esm.sh/[email protected]", "react-dom": "https://esm.sh/[email protected]", "utils": "./src/utils.js" }}
注意:type="importmap" 是强制的;JSON 中不能有注释;URL 必须是完整路径(相对路径会被解析为相对于当前 HTML 文档);键名不能以 / 开头,否则会被视为“范围映射”而非“裸 specifier”。
import 语句里怎么用映射后的名字只要 importmap 已加载,后续所有 import 都可直接使用映射名——它和 ESM 规范完全兼容:
立即学习“前端免费学习笔记(深入)”;
import { debounce } from "lodash";import App from "app";import { log } from "utils";
这些不会触发 404,前提是 importmap 里已声明对应键。常见错误包括:
importmap 前就执行了 import(比如 <script type="module"> 放在 <script type="importmap"> 上方)"Lodash" 但映射表里是 "lodash")import() 但未加引号(import("lodash") ✅,import(lodash) ❌)scopes 能解决什么问题当不同模块依赖同一包的不同版本,或你想为某个路径下的所有导入统一重写来源时,"scopes" 比 "imports" 更精准:
{ "imports": { "vue": "https://esm.sh/[email protected]" }, "scopes": { "./node_modules/legacy-app/": { "vue": "https://esm.sh/[email protected]" } }}
这样,只有从 ./node_modules/legacy-app/ 下发起的 import "vue" 才会命中 Vue 2,其他地方仍走 Vue 3。但要注意:scopes 的 key 必须是绝对路径或以 ./ 或 ../ 开头的相对路径;它不支持通配符或正则;且每个 scope 的匹配基于导入语句的 **引用者路径**,不是被导入模块的路径。
真正麻烦的是调试:浏览器开发者工具的 Sources 面板里看不到映射过程,出错时控制台报的仍是原始 specifier(比如 Failed to load module "lodash"),但实际请求的 URL 已被替换——你得手动查 importmap 内容并比对网络面板里的真实请求地址。