import maps

1,654 阅读2分钟

背景

  1. 我们使用commonjs AMD 等运行时模块加载系统,或者基于webpack browserify等打包构建工具的构建时模块加载能力,允许我们使用非常直接的模块导入方式(bare import specifiers):
import lodash from 'lodash';
import React from 'react';
...

但是原生的ESM(不依赖其他的构建工具的时候),在浏览器中并不支持这种简单的引用模块的方式

  1. 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>

功能&用法

  1. 别名:specifier remapping
{
    "imports": {
        "hello": "./utils/hello.js",
        "hello1": "/utils/hello.js",
        "utils/": "/utils/",
        "utils/hello": "/utils/hello.js",
        "scope": "/scope/index.js"
    },
   
}
  1. 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日)兼容性如下: image.png

兼容性查看: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`规范适用于那些运行时确认模块加载的情况,而非构建时确认模块加载的情况

哪些场景会用到

  1. 依赖于systemjs的场景

比如微前端框架single-spa依赖systemjs,所以如果你使用了single-spa实现微前端的话,你会用到它。

  1. 待补充

参考

  1. v8.dev/features/mo…
  2. github.com/WICG/import…
  3. caniuse.com/?search=imp…
  4. github.com/systemjs/sy…
  5. jspm.org/