浅谈 import-maps

2,467 阅读2分钟

这是我参与更文挑战的第 18 天,活动详情查看:更文挑战


前两天在使用 deno 时接触到了 import-maps ,在网上一查,发现居然是一个在 WICG 下的提案。面向未来的提案最好要提前了解布局。

先看看 import-maps 的样子

这是一个比较常见的 import-maps 实例

{
  "imports": {
    "moment": "/node_modules/moment/src/moment.js",
    "lodash": "/node_modules/lodash-es/lodash.js"
  }
}

配置 import-maps 后,可以在 js 文件中通过以下方法使用:

import moment from "/node_modules/moment/src/moment.js";
import { partition } from "/node_modules/lodash-es/lodash.js";

看到这个,很容易联想到开发项目时常用的 npm package.json

{
  "dependencies": {
    "lodash": "^4.17.21",
    "moment": "^2.29.1"
  }
}

(上面是简化的部分)

可以看出,import-maps 和 package.json 两者都可以实现模块功能映射,简化引用成本。

为什么要造两个类似的东西?两者又有什么相同点和不同点?

首先,简化打包工具,将大部分功能都改造为使用浏览器原生提供能力是一种趋势。通过使用原生能力,节省在构建转译部分的开销,是很划算的事情。

import-maps 就建立在这套基础上。根据官方标准文档提到:

Web developers with experience with pre-ES2015 module systems, such as CommonJS (either in Node or bundled using webpack/browserify for the browser), are used to being able to import modules using a simple syntax

Today, many web developers are even using JavaScript's native module syntax, but combining it with bare import specifiers, thus making their code unable to run on the web without per-application, ahead-of-time modification. We'd like to solve that, and bring these benefits to the web.

与 npm 的 package.json 相比,有着这些优点:

  1. 允许在浏览器中直接使用 import 标志符,比如:
import moment from "moment"
  1. 提供兜底解决方案,比如 import $ from "jquery",他先会去尝试去 CDN 引用这个库,如果 CDN 挂了可以回退到引用本地版本。
{
  "imports": {
    "jquery": [
      "https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js",
      "/node_modules/jquery/dist/jquery.js"
    ]
  }
}
  1. 开启对一些内置模块或者其他功能的 polyfill。
{
  "imports": {
    "/node_modules/kvs-polyfill/index.mjs": [
      "std:kv-storage",
      "/node_modules/kvs-polyfill/index.mjs"
    ]
  }
}
  1. 共享 import 标识符在 Javascript importing 上下文或者传统的 url 上下文,比如 fetch()、<img src="">或者<link href="">
.back-button {
  background: url('import:widget/assets/back.svg');
}