Chrome 71 版即將對 cache.addAll() 和 importScripts() 做出調整

使用服務工作者Cache Storage API 的開發人員應留意 Chrome 71 推出的兩項小變更。這兩項變更可讓 Chrome 的實作方式更符合規格和其他瀏覽器。

禁止非同步 importScripts()

importScripts() 會通知主要服務 worker 指令碼暫停目前的執行作業,從指定網址下載其他程式碼,並在目前的全域範圍中執行該程式碼。完成後,主要 Service Worker 指令碼就會繼續執行。importScripts() 可用於將主要服務 worker 指令碼分割成較小的片段,以便進行分類,或是用於匯入第三方程式碼,為服務 worker 新增功能。

瀏覽器會嘗試透過自動快取透過 importScripts() 拉入的所有內容,來減輕「下載並執行某些同步程式碼」可能發生的效能問題,也就是說,在初始下載作業完成後,執行匯入的程式碼所需的額外負荷非常少。

不過,瀏覽器必須知道在初始安裝後,不會有任何「意外」程式碼匯入服務工作站,才能讓這項功能正常運作。根據服務 worker 規格,呼叫 importScripts() 應該只在頂層服務 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));
});

服務工作程程式碼應如下所示:

// 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 和服務工作者,Chrome 71 中還有另一項小變更,以便與相關規格保持一致。當同一個網址多次傳遞至單一 cache.addAll() 呼叫時,規格說明指出,呼叫傳回的承諾應遭到拒絕。

在 Chrome 71 之前,系統不會偵測到這項問題,因此會有效忽略重複的網址。

Chrome 控制台中的警告訊息螢幕截圖
從 Chrome 71 開始,您會在控制台看到記錄的警告訊息。

這項記錄功能是 Chrome 72 的序曲,在該版本中,重複的網址會導致 cache.addAll() 拒絕,而非僅記錄警告。如果您呼叫 cache.addAll() 做為傳遞至 InstallEvent.waitUntil() 的承諾鏈結的一部分,這會導致服務工作者無法安裝。

以下說明您可能遇到的問題:

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'),則不會觸發拒絕。

廣泛測試服務 worker 實作

目前,服務工作者已在所有主要的「永久更新」瀏覽器廣泛實作。如果您定期針對多個瀏覽器測試漸進式網頁應用程式,或是有大量使用者不使用 Chrome,那麼您很可能已經發現不一致性,並更新了程式碼。不過,如果您在其他瀏覽器中未發現這項行為,我們想在變更 Chrome 行為前先說明這項變更。