对 Chrome 71 中的 cache.addAll() 和 importScripts() 进行了调整

使用 Service WorkerCache 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 控制台中警告消息的屏幕截图
从 Chrome 71 开始,您会在控制台中看到一条警告消息。

此日志记录是 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 的行为之前列出相关更改。