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

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

不允許非同步 importScripts()

importScripts() 會指示主要服務工作站指令碼暫停目前的執行作業、從特定網址下載額外程式碼,並在目前的全域範圍中執行指令碼。完成後,主要服務工作站指令碼就會繼續執行。當您基於機構考量,而想將主要服務工作站指令碼分割成較小的檔案,或是插入第三方程式碼來為服務工作站新增功能時,importScripts() 非常實用。

瀏覽器會自動快取透過 importScripts() 提取的內容,藉此減少「下載並執行部分同步程式碼」可能帶來的效能問題,這表示在初始下載後,執行匯入的程式碼幾乎不會造成負擔。

但為此,瀏覽器必須知道在初次安裝後,系統不會將任何「意外」程式碼匯入 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() 的單一呼叫,規格說明呼叫傳回的承諾應拒絕。

在 Chrome 71 以下版本中,系統並未偵測到這類問題,並會有效忽略重複的網址。

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

在 Chrome 72 版推出這項記錄前,重複網址將導致 cache.addAll() 拒絕,而不只是系統記錄的警告。如果您根據常見的做法,在傳遞至 InstallEvent.waitUntil() 的承諾鏈中呼叫 cache.addAll(),則可能導致服務工作站無法安裝。

以下列出您可能會遇到的麻煩:

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 的實作

目前,服務工作站已在所有主要「長期」瀏覽器全面實作。如果您會定期針對各種瀏覽器測試漸進式網頁應用程式,或是有大量未使用 Chrome 的使用者,或許已經偵測到不一致並更新了程式碼。不過,您可能從未在其他瀏覽器中註意到這個行為,因此我們想在切換 Chrome 的行為前先提出變更。