importScripts() 的现代替代方案。
背景
ES 模块 已有一段时间被开发者最青睐。除了 许多其他优势 它们提供一种通用模块格式, 一次发布,可在浏览器和替代运行时(例如 Node.js。虽然 所有新型浏览器 提供一些 ES 模块支持,但并非在所有地方都提供支持 可以运行具体而言,支持导入 浏览器的 Service Worker 。
本文详细介绍了 Service Worker 中 ES 模块支持的当前状态 以及需要避免的一些陷阱, 交付向后兼容的 Service Worker 代码。
使用场景
Service Worker 内 ES 模块的理想应用场景是: 与其他运行时共享的现代库或配置代码 支持 ES 模块。
在 ES 模块之前尝试以这种方式共享代码会导致使用旧版模块 "通用"模块格式,例如 UMD,这些模块包括 不需要的样板文件,以及编写对全局公开代码进行更改的代码 变量。
通过 ES 模块导入的脚本可以触发 Service Worker
更新
会改变其内容,从而匹配
行为
/
importScripts()
。
当前限制
仅限静态导入
ES 模块可通过以下两种方式之一导入:
静态地
使用 import ... from '...'
语法,或者
动态,
使用 import()
方法。在 Service Worker 内,只有静态
语法。
此限制类似于
类似限制
对 importScripts()
的使用施加了限制。不会动态调用 importScripts()
在 Service Worker 内部工作,并且所有 importScripts()
调用(也就是
本质上是同步的,必须在 Service Worker 完成其
install
阶段。此限制可确保浏览器了解并
能够隐式缓存 Service Worker 所需的全部 JavaScript 代码,
在安装过程中实施。
最终,这一限制可能会取消, 模块导入 可能允许。 目前,请确保您仅在 Service Worker。
其他工作器呢?
支持
“专用”模块中的 ES 模块工作器数量 -
使用 new Worker('...', {type: 'module'})
构建的应用更加广泛,并且
在 Chrome 和 Edge 中
版本 80,以及
最新版本的 Safari。
专用 worker 同时支持静态和动态 ES 模块导入。
Chrome 和 Edge 在 共享工作器 从版本 83 开始,但不 其他浏览器目前提供支持。
不支持导入地图
允许导入地图 运行时环境来重写模块说明符,例如将模块说明符 可从中加载 ES 模块的首选 CDN 的网址。
而 Chrome 和 Edge 版本 89 及更高版本 支持导入地图, 无法用于服务 worker。
浏览器支持
Chrome 和 Edge 支持 Service Worker 中的 ES 模块,从 91 版。
Safari 在 技术预览版 122, 开发者应该会在 Safari 版本。
示例代码
这是在 Web 应用的 window
中使用共享 ES 模块的基本示例
上下文,同时还要注册使用同一 ES 模块的 Service Worker:
// Inside config.js:
export const cacheName = 'my-cache';
// Inside your web app:
<script type="module">
import {cacheName} from './config.js';
// Do something with cacheName.
await navigator.serviceWorker.register('es-module-sw.js', {
type: 'module',
});
</script>
// Inside es-module-sw.js:
import {cacheName} from './config.js';
self.addEventListener('install', (event) => {
event.waitUntil((async () => {
const cache = await caches.open(cacheName);
// ...
})());
});
向后兼容性
如果所有浏览器都支持以上示例中的 ES 模块, Service Worker,但在撰写本文时,情况并非如此。
要适应没有内置支持的浏览器,您可以
通过 Service Worker 脚本
ES 模块兼容打包器 - 用于创建
Service Worker,其中包含所有内嵌的模块代码,
版本较低的浏览器。另外,如果您要导入的模块
捆绑在
IIFE 或
UMD 格式,您可以使用
importScripts()
。
获得两个版本的 Service Worker 后,其中一个版本使用 ES 其他模块,则您需要检测当前 并注册相应的 Service Worker 脚本。最佳 目前有多种方法用于检测支持情况,但您可以按照 讨论 GitHub 问题 建议。
_摄影:Vlado Paunovic 在 Unsplash 网站发布