笔记地址:SystemJS 和 import-map-overrides
SystemJS 诞生于 2015 年,那个时候 ES Module 还未成为标准,在浏览器端只能通过 requirejs、seajs 等方案实现模块加载,SystemJS 最初诞生的目的是为了做一个通用的模块加载器,在浏览器端实现对 CommonJS、AMD、UMD 等各种模块的加载。
Script标签的基本属性
nomodule
这个布尔属性被设置来标明这个脚本在支持 ES2015 modules 的浏览器中不执行。
实际上,这可用于在不支持模块化JavaScript的旧浏览器中提供回退脚本。
<script type="module" src="main.mjs"></script>
<script nomodule src="fallback.js"></script>
type
属性的值为MIME类型:
- text/javascript
- text/ecmascript
- application/javascript
- application/ecmascript
- 如果没有定义type这个属性,也就是忽略type字段,脚本会被视作JavaScript
- 如果type属性为module,代码会被当作JavaScript模块 。请参见ES6 in Depth: Modules
- 如果MIME类型不是JavaScript类型(上述支持的类型),则该元素所包含的内容会被当作数据块而不会被浏览器执行
Content Security Policy
Content Security Policy (CSP) 文档地址
- 可以使用 meta 标签来配置策略:
<meta http-equiv="Content-Security-Policy"
content="default-src 'self'; img-src https://*; child-src 'none';">
- 可以使用 csp的http头来声明策略:
Content-Security-Policy: policy
SystemJS 提供的 type="systemjs-importmap"
<script type="systemjs-importmap">
{
"imports": {
"moment": "https://cdn.jsdelivr.net/npm/moment/dist/moment.js",
"lodash": "https://cdn.jsdelivr.net/npm/lodash/dist/lodash.js"
}
}
</script>
<script src="https://cdn.jsdelivr.net/npm/systemjs/dist/system.js"></script>
systemjs与webpack互操作
webpack有一些用于提升 systemjs与webpack的互操作性的特性
webpack - libraryTarget: 'system'
以下内容都可以在 webpack官方文档(v4和v5)的说明里找到。
从webpack@4.30.0开始,提供 libraryTarget: 'system' 这个参数,这样webpack编译的库会提供一个作为 System.register 模块的库。
- webpack编译生成的System模块要求 System 作为一个全局变量出现在浏览器的运行环境里;
- webpack编译生成的库,符合System.register格式,使用System.import引入无需额外的配置,就可以让webpack bundle 加载进入 System 的 module registry;
webpack - Rule.parser : system
Rule的作用:创建模块时,匹配请求的规则数组。这些规则能够修改模块的创建方式。这些规则能够对模块(module)应用 loader,或者修改解析器(parser)。
Rule.parser的作用:解析选项对象。所有应用的解析选项都将合并。解析器(parser)可以查阅这些选项,并相应地禁用或重新配置,包含了 system 默认值是 false。
systemjs#compatibility-with-webpack
如果 webpack@<5 的话,需要添加这样的配置,避免重写全局 System 对象的引用
{
module: {
rules: [
{ parser: { system: false } }
]
}
}
import-map-overrides
github地址:import-map-overrides
-
是一个 in-brower 和 nodejs 模块,可以重写 import map功能;
-
可以和 浏览器 原生 import maps 协同工作;
可以和 SystemJS 的 import maps 系统工作;
可以和 es-module-shims的 importmaps 协同工作;
-
他把覆写信息(override)保存在浏览器本地的 storage 里面,以便用户可以动态的修改 js 模块的 url;
-
开发者可以单独替换某一个模块到他们的本地开发环境,而不必重启本地环境、开发服务器或者其他环境;
Import Map Type
他默认与浏览器原生的Import Map工作,如果需要和其他模块协同,需要明确指定
例如,使用 SystemJS:
Override Mode
| Mode | Native import maps | SystemJS | es-module-shims | Works with ****external maps | Overrides when server rendering | Easy to set up |
|---|---|---|---|---|---|---|
| Client-side multiple maps | ❌ | ✅ | ✅ | ✅ | ❌1 | ✅ |
| Client-side single map | ✅ | ✅ | ✅ | ❌2 | ❌1 | ✅ |
| Server-side multiple maps | ❌ | ✅ | ✅ | ✅ | 🤔3 | ❌ |
| Server-side single map | ✅ | ✅ | ✅ | ✅ | ✅4 | ❌ |
他的四种模式:
-
Client-side multiple maps (default)
-
使用这种模式,将 type="overridable-importmap"
Domain List
启用 domains这个功能:
- 在header中添加: ;
- 可以在 meta的content字段设置两种:denylist和allowlist;
<!-- Disable the entirety of import-map-overrides unless you're on the dev or stage environments -->
<meta
name="import-map-overrides-domains"
content="allowlist:dev.example.com,stage.example.com"
/>
<!-- Disable the entirety of import-map-overrides when you're on the production environment -->
<meta name="import-map-overrides-domains" content="denylist:prod.example.com" />
<!-- You can also use wildcards url -->
<meta
name="import-map-overrides-domains"
content="allowlist:*.example.com,example-*.com"
/>
安全
- 强烈推荐:在你的server上设置你的html的 CSP 的 http 请求头来 确保安全;
- 考虑在生产环境上删除 import-map-override 段,或者配置 domain list;
API
该库加载了之后,会在window全局建立自己的对象,在这个对象上有所有的API接口可以调用。
window.importMapOverrides
两个事件 init 和 change
// init 事件
window.addEventListener("import-map-overrides:init", () => {
console.log('init');
})
// change 事件
window.addEventListener("import-map-overrides:change", logImportMap);
// Later on you can remove the event listener
window.removeEventListener("import-map-overrides:change", logImportMap);
function logImportMap(evt) {
console.log(window.importMapOverrides.getOverrideMap());
}
启用 UI
你可以在Dom中为他准备一个节点,这样就可以在界面上操作。有以下三种方法:
<!-- 这是全UI,包含了 trigger 按钮
show-when-local-storage 属性介绍:
1,忽略show-when-local-storage这个属性,黄色/橘色方块始终可见;
2,设置他的属性为某一个值,那么需在控制台console中使用
localStorage.setItem('overrides-ui', true); 控制 UI 可见;
dev-libs 属性介绍:
加上这个属性之后,会优先选择 deveopment 版本的js。
想要关闭那么可以调用: `localStorage.setItem('import-map-overrides-dev-libs', false)` 关闭。
设置 true 就可以开启
-->
<import-map-overrides-full
show-when-local-storage="overrides-ui"
dev-libs
></import-map-overrides-full>
<!-- Alternatively, just the black popup itself -->
<import-map-overrides-popup></import-map-overrides-popup>
<!-- Or if you only want the actual import map list and UI for overriding -->
<import-map-overrides-list></import-map-overrides-list>
<!-- Or if you prefer enabling via javascript -->
<script>
importMapOverrides.enableUI();
</script>
import-map-deployer
github地址: import-map-deployer
是后端服务更新 import map json files的工具库。当使用 import-map-deployer的时候,一个前端开发完全准寻以下两步:
- 上传js文件到CDN;
- 发送一个http请求去修改已存在的 import map指向新的文件;