背景
- 我们使用
commonjs AMD
等运行时模块加载系统,或者基于webpack browserify
等打包构建工具的构建时模块加载能力,允许我们使用非常直接的模块导入方式(bare import specifiers
):
import lodash from 'lodash';
import React from 'react';
...
但是原生的ESM
(不依赖其他的构建工具的时候),在浏览器中并不支持这种简单的引用模块的方式
ESM
原生用法
// ok
import log from '/utils/log.js';// it will be loaded from ${domain}/utils/log.js
import log from './utils/log.js';
import log from 'https://aaa.com/utils/log.js';
// not work
import log from 'log';
// not work
import log from './utils/log';// ignore the suffix of the file
- 只能支持相对路径或者是完整的
url
- 需要注意的是上面的所有正确的用法都是运行时加载(理解成通过动态创建
script
标签加载脚本的方式即可)
总结上述:import maps 就是为了能够简化模块引用的方式,简单可以理解成模块别名,当然还有一些其他的特性。
使用方式
// inline
<script type="importmap">
{
"imports": { ... },
"scopes": { ... }
}
</script>
// with a src
<script type="importmap" src="import-map.importmap"></script>
功能&用法
- 别名:
specifier remapping
{
"imports": {
"hello": "./utils/hello.js",
"hello1": "/utils/hello.js",
"utils/": "/utils/",
"utils/hello": "/utils/hello.js",
"scope": "/scope/index.js"
},
}
scope
允许指定特定的路径下的模块单独设置别名(覆盖全局imports
的配置)
{
"imports": {
"hello": "./utils/hello.js",
"hello1": "/utils/hello.js",
"utils/": "/utils/",
"utils/hello": "/utils/hello.js",
"scope": "/scope/index.js"
},
"scopes": {
// scope目录下的模块中 会使用下面的remapping规则覆盖上面的imports规则,如当前scope下没有的别名配置,则从上面查找(类似css中的继承特性)
"/scope/": {
"hello": "./utils/hello-v2.js"
}
}
}
示例demo:codesandbox.io/s/loving-la…
兼容性以及实现(compatibility & implementation
)
截止当前(2021年 9月 5日)兼容性如下:
兼容性查看:can-i-use;所以想在生产环境下使用还是需要一些兼容实现方案。
实现:参考sytemjs
systemjs
systemjs 是一个模块加载器,和
requirejs seajs
等类似
为什么systemjs
要实现import maps
?
其实import maps
提案本质上就是alias
,类似requirejs-paths, 或者是我们熟悉的webpack alias
(当然webpack
的模块查找过程是在building time
, 而systemjs or requirejs
是在runtime
过程)
总结来说,
systemjs
其实就是参考import maps
规范实现了它自己的alias
为啥感觉我们不太需要它?
- 一般我们会依赖`webpack rollup`这些构建工具,对前端工程进行编译、构建打包,这些打包、构建工具都有自己的模块查找机制,支持对应的**模块别名**能力
- 另外,`import maps`规范适用于那些运行时确认模块加载的情况,而非构建时确认模块加载的情况
哪些场景会用到
- 依赖于
systemjs
的场景
比如微前端框架single-spa依赖systemjs
,所以如果你使用了single-spa实现微前端的话,你会用到它。
- 待补充