使用 Service Worker 和 Cache Storage API 的开发者应留意 Chrome 71 中推出的两项小变更。这两项变更都会使 Chrome 的实现更加符合规范和其他浏览器。
禁止异步 importScripts()
importScripts()
指示您的主 Service Worker 脚本暂停其当前执行,从给定网址下载其他代码,并在当前全局范围内运行这些脚本直至完成。完成该操作后,主 Service Worker 脚本将继续执行。当您出于组织原因需要将主 Service Worker 脚本分解为较小的片段时,或者需要引入第三方代码向 Service Worker 添加功能时,importScripts()
会派上用场。
浏览器会尝试通过自动缓存通过 importScripts()
提取的任何内容,来尝试缓解“下载并运行一些同步代码”可能带来的性能问题,也就是说,在初始下载后,执行导入的代码所需的开销非常小。
不过,要使该操作正常工作,浏览器需要知道在初始安装后,不会向 Service Worker 中导入任何“意外”代码。根据 Service Worker 规范,调用 importScripts()
应该仅在同步执行顶级 Service Worker 脚本期间有效,或者在需要时,在 install
处理程序内异步执行。
在 Chrome 71 之前,可以在 install
处理程序之外异步调用 importScripts()
。从 Chrome 71 开始,这些调用会抛出运行时异常(除非之前在 install
处理程序中导入了同一网址),这与在其他浏览器中的行为一致。
不要使用如下代码:
// This only works in Chrome 70 and below.
self.addEventListener('fetch', event => {
importScripts('my-fetch-logic.js');
event.respondWith(self.customFetchLogic(event));
});
您的 Service Worker 代码应如下所示:
// Move the importScripts() to the top-level scope.
// (Alternatively, import the same URL in the install handler.)
importScripts('my-fetch-logic.js');
self.addEventListener('fetch', event => {
event.respondWith(self.customFetchLogic(event));
});
弃用传递给 cache.addAll() 的重复网址
如果您将 Cache Storage API 与 Service Worker 搭配使用,Chrome 71 中会进行另一项细微更改,以符合相关规范。当同一网址多次传递到对 cache.addAll()
的单次调用时,规范指出该调用返回的 promise 应拒绝。
在 Chrome 71 之前,系统不会检测到此类网址,并且会实际忽略重复的网址。
![Chrome 控制台中警告消息的屏幕截图](https://developer.chrome.google.cn/static/blog/tweeks-to-addAll-importScripts/image/a-screenshot-the-warning-46bead1fd2604.png?authuser=5&hl=nb)
此日志记录是 Chrome 72 的序曲,在 Chrome 72 中,重复网址不仅是记录的警告,还会导致 cache.addAll()
拒绝网址。如果您是在传递给 InstallEvent.waitUntil()
的 promise 链中调用 cache.addAll()
,通常的做法是,该拒绝可能会导致您的 Service Worker 无法安装。
您可能会遇到以下问题:
const urlsToCache = [
'/index.html',
'/main.css',
'/app.js',
'/index.html', // Oops! This is listed twice and should be removed.
];
self.addEventListener('install', event => {
event.waitUntil(
caches.open('my-cache').then(cache => cache.addAll(urlsToCache))
);
});
此限制仅适用于传递给 cache.addAll()
的实际网址,缓存最终产生两个具有不同网址的等效响应(例如 '/'
和 '/index.html'
)不会触发拒绝操作。
广泛测试 Service Worker 实现
此时,在所有主流“常青”浏览器中广泛实现 Service Worker。如果您定期针对多种浏览器测试渐进式 Web 应用,或者有大量用户不使用 Chrome,那么您可能已经检测到不一致的情况并更新了代码。然而,您可能并未在其他浏览器中注意到此行为,因此我们想在切换 Chrome 的行为之前列出相关更改。