Skip to main content

ESM

caution
tip

import map

<script type="importmap">
{
"imports": {
"moment": "/node_modules/moment/src/moment.js",
"lodash": "/node_modules/lodash-es/lodash.js"
}
}
</script>
<!-- application/importmap+json -->
<script type="importmap" src="import-map.importmap"></script>
动态构建
<script>
if (HTMLScriptElement.supports && HTMLScriptElement.supports('importmap')) {
console.log('Your browser supports import maps.');
}

const importMap = {
imports: {
moment: '/moment.mjs',
lodash: someFeatureDetection() ? '/lodash.mjs' : '/lodash-legacy-browsers.mjs',
},
};

const im = document.createElement('script');
im.type = 'importmap';
im.textContent = JSON.stringify(importMap);
document.currentScript.after(im);
</script>

<script type="module">
import _ from 'lodash'; // will fetch the right URL for this browser
</script>
importmap 规范
{
"imports": {
// import moment from "moment";
"moment": "/node_modules/moment/src/moment.js",
// 自动映射
// import localeData from "moment/locale/zh-cn.js";
"moment/": "/node_modules/moment/src/",
"lodash": "/node_modules/lodash-es/lodash.js",
// import fp from "lodash/fp.js";
"lodash/": "/node_modules/lodash-es/",
// 无扩展名
// import fp from "lodash/fp"
"lodash/fp": "/node_modules/lodash-es/fp.js",

// remapping - 对 <script> 不生效
"https://www.unpkg.com/vue/dist/vue.runtime.esm.js": "/node_modules/vue/dist/vue.runtime.esm.js",
// 前缀 remmaping
"https://www.unpkg.com/vue/": "/node_modules/vue/",
"/app/helpers.mjs": "/app/helpers/index.mjs",

// 常见处理 hash 场景
"/js/app.mjs": "/js/app-8e0d62a03.mjs"
},
// 限定上下文,修改依赖
"scopes": {
"/scope2/": {
"a": "/a-2.mjs"
},
"/scope2/scope3/": {
"b": "/b-3.mjs"
}
}
}

CDN

cdnimportgithubcjs -> esm
Skypackhttps://cdn.skypack.dev/
esm.shhttps://esm.sh/esm-dev/esm.sh
jsDelivrhttps://cdn.jsdelivr.net/npm/
JSPMhttps://ga.jspm.io/npm:[email protected]/jspm/project
unpkghttps://unpkg.com/${PKG}?modulemjackson/unpkg

CDN Test

for i in $(seq 3); do

rm bench-*.txt
for i in $(seq 10); do
curl -o /dev/null -s -w "%{time_total}\n" https://cdn.skypack.dev/[email protected] >> bench-a.txt
curl -o /dev/null -s -w "%{time_total}\n" https://cdn.jsdelivr.net/npm/[email protected]/+esm >> bench-b.txt
curl -o /dev/null -s -w "%{time_total}\n" https://esm.sh/[email protected] >> bench-c.txt
done
for i in bench-*.txt; do
echo $i
awk '{ total += $1; count++ } END { print total/count }' $i
done

done

esm.sh

  • 可以 Selfhosted
  • 主服务器在 HK
  • 基于 esbuild 构建
  • cjs -> esm 使用 swc
  • 支持 X-Typescript-Types 头 - demo 类型检测
    • ?no-check 禁用
import React from 'https://esm.sh/[email protected]';
// 非模块文件
import 'https://esm.sh/tailwindcss/dist/tailwind.min.css';
// bundle 模式
import { Button } from 'https://esm.sh/antd?bundle';
// 开发模式
import React from 'https://esm.sh/react?dev';
// 依赖控制
import React from 'https://esm.sh/[email protected]';
import useSWR from 'https://esm.sh/[email protected]';
// 别名
import useSWR from 'https://esm.sh/swr?alias=react:preact/compat&[email protected]';
// 目标版本 - 默认基于 header 判断
import React from 'https://esm.sh/react?target=es2020';
// WebWorker
import editorWorker from '/monaco-editor/esm/vs/editor/editor.worker?worker';
const worker = new editorWorker();