從 Workbox v2 遷移至第 3 版

本指南著重於 Workbox v3 中導入的破壞性變更,並提供從 Workbox v2 設定升級時需要進行哪些變更。

如果您目前使用的是舊版 sw-precache/sw-toolbox 組合,且想要初次改用 Workbox,請參閱這份遷移指南

v3 背景

Workbox 的 v3 版本代表現有的程式碼集大幅重構。首要目標如下:

  • 盡量減少 Workbox 的大小。已降低下載及執行的 Service Worker 執行階段程式碼數量。系統只會在執行階段匯入您使用的特定功能的程式碼,而非讓所有使用者加入單體式套件。
  • Workbox 有 CDN。我們提供全面支援的 Google Cloud Storage CDN 託管服務,做為存取 Workbox 執行階段程式庫的標準選項,讓您更容易開始使用 Workbox。
  • 更完善的偵錯和記錄功能。偵錯和記錄功能已大幅改善。每當 localhost 來源使用 Workbox,而且所有記錄和宣告都會從正式版本中移除,系統就會啟用偵錯記錄。 Workbox v3 提供的偵錯記錄範例。
  • 改善 Webpack 外掛程式。workbox-webpack-plugin 可更密切地與 Webpack 建構程序整合,方便您在建構管道中預先快取所有資產時,使用零設定用途。

為了達成這些目標,並清除舊版介面中感到不安或造成反面模式的部分,請務必在 v3 版本中導入一些破壞性變更。

破壞性變更

建構設定

以下變更會影響所有建構工具 (workbox-buildworkbox-cliworkbox-webpack-plugin) 的行為,這些工具皆共用一組通用的設定選項。

  • 'fastest' 處理常式名稱先前有效,且在設定 runtimeCaching 時視為 'staleWhileRevalidate' 的別名。此狀態已失效,開發人員應直接改用 'staleWhileRevalidate'
  • 我們更新了數個 runtimeCaching.options 屬性名稱,並有其他參數驗證功能,如果使用無效的設定,會導致建構失敗。如需目前支援選項的清單,請參閱 runtimeCaching說明文件

工作箱-背景同步

  • maxRetentionTime 設定參數現在會解譯為分鐘數,而非毫秒。
  • 現在有代表佇列名稱的必要字串,這些字串必須在建構外掛程式或獨立類別時傳入,做為第一個參數。(這個引數先前是以選項屬性的形式傳入)。如需更新版 API 介面,請參閱說明文件

workbox-broadcast-cache-update

  • 現在有代表頻道名稱的必要字串,當您建構外掛程式或獨立類別時,必須傳入此字串做為第一個參數。

舉例來說,在 v2 中,您可以依照下列方式初始化外掛程式類別:

new workbox.broadcastCacheUpdate.BroadcastCacheUpdatePlugin({
  channelName: 'cache-updates',
  headersToCheck: ['etag'],
});

第 3 版中的同等用途如下:

new workbox.broadcastUpdate.Plugin('cache-updates', {headersToCheck: ['etag']});

如需更新版 API 介面,請參閱說明文件

Workbox-build

  • 根據預設,現在將使用選項 follow: true (將追蹤符號連結) 和 strict: true (對「異常」錯誤的容忍度較低) 執行 glob 模式比對。您可以在建構設定中設定 globFollow: false 和/或 globStrict: false,藉此停用任一選項並返回先前的行為。
  • workbox-build 中的函式都會在傳回的回應中傳回額外屬性 warnings。現在允許在第 2 版中視為嚴重錯誤的情況,但可以透過 warnings (這個字串陣列) 回報。

在第 2 版中,您可以呼叫 generateSW,例如:

const workboxBuild = require('workbox-build');

workboxBuild.generateSW({...})
  .then(({count, size}) => console.log(`Precached ${count} files, totaling ${size} bytes.`))
  .catch((error) => console.error(`Something went wrong: ${error}`));

雖然您可以在 v3 中使用相同的程式碼,但建議您檢查並記錄任何 warnings

const workboxBuild = require('workbox-build');

workboxBuild.generateSW({...})
  .then(({count, size, warnings}) => {
    for (const warning of warnings) {
      console.warn(warning);
    }
    console.log(`Precached ${count} files, totalling ${size} bytes.`);
  })
  .catch((error) => console.error(`Something went wrong: ${error}`));
  • 在第 2 版中自行編寫自訂 ManifestTransform 函式的開發人員需要在物件中傳回資訊清單陣列 (也就是說,您應使用 return {manifest: manifestArray};,而非 return manifestArray;)。m 這樣可讓外掛程式納入選用的 warnings 屬性,該屬性應為包含非重大警告資訊的字串陣列。

如果您是在 v2 中編寫自訂的 ManifestTransform,則程式碼如下:

const cdnTransform = manifestEntries => {
  return manifestEntries.map(entry => {
    const cdnOrigin = 'https://example.com';
    if (entry.url.startsWith('/assets/')) {
      entry.url = cdnOrigin + entry.url;
    }
    return entry;
  });
};

的第 3 版相當於:

const cdnTransform = manifestEntries => {
  const manifest = manifestEntries.map(entry => {
    const cdnOrigin = 'https://example.com';
    if (entry.url.startsWith('/assets/')) {
      entry.url = cdnOrigin + entry.url;
    }
    return entry;
  });
  return {manifest, warnings: []};
};
  • getFileManifestEntries() 函式已重新命名為 getManifest(),且傳回的 promise 現在包含已預先快取網址的額外資訊

第 2 版中的程式碼如下:

const manifestEntries = await workboxBuild.getFileManifestEntries({...});

可在第 3 版中重新編寫,如下所示:

const {manifestEntries, count, size, warnings} = await workboxBuild.getManifest({...});

// Use manifestEntries like before.
// Optionally, log the new info returned in count, size, warnings.
  • 已移除 generateFileManifest() 函式。我們建議開發人員改為呼叫 getManifest(),然後透過回應以適當的格式將資料寫入磁碟。

工作箱-快取效期

  • Plugin API 維持不變,大多數開發人員會使用此模式。不過,開發人員將 API 做為獨立類別使用的開發人員有重大的 API 變更。如需更新版 API 介面,請參閱說明文件

workbox-cli

開發人員可透過 --help 標記,針對一組完整的支援參數執行 CLI。

  • 已移除對二進位指令碼的 workbox-cli 別名支援功能。二進位檔現在只能以 workbox 身分存取。
  • v2 指令 generate:swinject:manifest 在 v3 中已重新命名為 generateSWinjectManifest
  • 在 v2 中,系統會將預設的設定檔 (在未明確提供時使用) 視為目前目錄中的 workbox-cli-config.js。在 第 3 版中則為 workbox-config.js

將兩者合併,意味著在第 2 版中:

$ workbox inject:manifest

會透過 workbox-cli-config.js 和 v3 讀取的設定,執行「插入資訊清單」建構程序:

$ workbox injectManifest

會產生相同,但從 workbox-config.js 讀取設定。

工作箱預先快取

  • 先前 precache() 方法會修改快取內容,並設定路徑來提供快取項目。現在,precache() 僅修改快取項目,而新的方法 addRoute() 已公開用於註冊路徑,以提供這些快取的回應。開發人員如想要先前的雙重功能,可以改為呼叫 precacheAndRoute()
  • 過去透過 WorkboxSW 建構函式設定的數個選項,現在會以 workbox.precaching.precacheAndRoute([...], options) 中的 options 參數的形式傳遞。參考文件中會列出這些選項的預設值 (如未設定)。
  • 根據預設,系統會自動檢查缺少副檔名的網址,是否與包含 .html 副檔名的快取項目進行比對。舉例來說,如果針對 /path/to/index 提出要求 (未預先快取),且有 /path/to/index.html 的預快取項目,系統就會使用該預快取項目。開發人員在將選項傳入 workbox.precaching.precacheAndRoute() 時,設定 {cleanUrls: false} 即可停用這個新行為。
  • 系統不會再自動設定 workbox-broadcast-update,以宣告預快取資產的快取更新。

第 2 版中的下列程式碼:

const workboxSW = new self.WorkboxSW({
  directoryIndex: 'index.html',
  ignoreUrlParametersMatching: [/^utm_/],
  precacheChannelName: 'precache-updates',
});
workboxSW.precache([...]);

的第 3 版相當於:

workbox.precaching.addPlugins([
    new workbox.broadcastUpdate.Plugin('precache-updates')
]);

workbox.precaching.precacheAndRoute([...], {
  cleanUrls: false,
  directoryIndex: 'index.html',
  ignoreUrlParametersMatching: [/^utm_/],
});

工作箱轉送

  • 先前透過 WorkboxSW 物件的 workbox.router.* 命名空間使用 workbox-routing 的開發人員,必須改用新的命名空間 workbox.routing.*
  • 系統現在會依據先註冊的先進順序評估路徑。這是第 2 版使用的 Route 評估結果「相反」,系統會優先採用上次註冊的 Route
  • ExpressRoute 類別和已支援「Express-style」萬用字元。這樣可大幅縮減 workbox-routing 的大小。現在做為 workbox.routing.registerRoute() 的第一個參數字串將視為完全比對。萬用字元或部分比對項目應由 RegExp 處理,使用任何與部分或所有要求網址相符的 RegExp 即可觸發路徑。
  • 已移除 Router 類別的 addFetchListener() 輔助方法。開發人員可以明確新增自己的 fetch 處理常式或使用 workbox.routing 提供的介面,以隱含方式為自己建立 fetch 處理常式。
  • 已移除 registerRoutes()unregisterRoutes() 方法。在單一 Route 上執行的方法版本並未變更,且需要一次註冊或取消註冊多個路徑的開發人員應改為對 registerRoute()unregisterRoute() 發出一系列呼叫。

第 2 版中的下列程式碼:

const workboxSW = new self.WorkboxSW();

workboxSW.router.registerRoute(
  '/path/with/.*/wildcard/',
  workboxSW.strategies.staleWhileRevalidate()
);

workboxSW.router.registerRoute(
  new RegExp('^https://example.com/'),
  workboxSW.strategies.networkFirst()
);

的第 3 版相當於:

workbox.routing.registerRoute(
  new RegExp('^https://example.com/'),
  workbox.strategies.networkFirst()
);

workbox.routing.registerRoute(
  new RegExp('^/path/with/.*/wildcard'),
  workbox.strategies.staleWhileRevalidate()
);

工作箱策略 (先前稱為 Workbox-runtime-caching)

  • workbox-runtime-caching 模組現已正式稱為 workbox-strategies,並npm 發布,即採用新名稱。
  • 如果未一併提供快取名稱,在策略中使用快取到期時間就會失效。在 v2 中,可能的情況如下:
workboxSW.strategies.staleWhileRevalidate({
  cacheExpiration: {maxEntries: 50},
});

這會導致預設快取中的項目過期,這是非預期的情況。在 v3 中,快取名稱為必填欄位:

workboxSW.strategies.staleWhileRevalidate({
  cacheName: 'my-cache',
  plugins: [new workbox.expiration.Plugin({maxEntries: 50})],
});
  • cacheWillMatch 生命週期方法已重新命名為 cachedResponseWillBeUsed。除非開發人員自行編寫會回應 cacheWillMatch 的外掛程式,否則這應該不是明顯的變更。
  • 設定策略時指定外掛程式的語法已變更。每個外掛程式都必須在策略設定的 plugins 屬性中明確列出。

第 2 版中的下列程式碼:

const workboxSW = new self.WorkboxSW();

const networkFirstStrategy = workboxSW.strategies.networkFirst({
  cacheName: 'my-cache',
  networkTimeoutSeconds: 5,
  cacheExpiration: {
    maxEntries: 50,
  },
  cacheableResponse: {
    statuses: [0, 200],
  },
});

的第 3 版相當於:

const networkFirstStrategy = workbox.strategies.networkFirst({
  cacheName: 'my-cache',
  networkTimeoutSeconds: 5,
  plugins: [
    new workbox.expiration.Plugin({maxEntries: 50}),
    new workbox.cacheableResponse.Plugin({statuses: [0, 200]}),
  ],
});

詳情請參閱「使用外掛程式」指南。

Workbox-SW

  • 基本上,workbox-sw 已改寫為輕量的「載入器」介面,該介面需要一些基本設定,並負責提取執行階段所需的其他模組。開發人員會與在全域命名空間中自動公開的現有執行個體互動,而不是建構 WorkboxSW 類別的新執行個體。

第 2 版:

importScripts('<path to workbox-sw>/importScripts/workbox-sw.prod.v2.1.3.js');

const workbox = new WorkboxSW({
  skipWaiting: true,
  clientsClaim: true,
  // etc.
});

workbox.router.registerRoute(...);

在 v3 中,您只需匯入 workbox-sw.js 指令碼,系統就會自動在全域命名空間中以 workbox 形式提供可供使用的執行個體:

importScripts('<path to workbox-sw>/3.0.0/workbox-sw.js');

// workbox is implicitly created and ready for use.
workbox.routing.registerRoute(...);
  • skipWaitingclientsClaim 不再是傳遞至 WorkboxSW 建構函式的選項。而已改為 workbox.clientsClaim()workbox.skipWaiting() 方法。
  • 第 2 版建構函式支援的 handleFetch 選項,v3 不再支援。如果開發人員需要使用類似功能測試 Service Worker,而不叫用任何擷取處理常式,可以使用 Chrome 開發人員工具中的「略過網路」選項。
Chrome 開發人員工具中的「略過網路」選項。

工作箱-webpack-外掛程式

此外掛程式已大幅重新編寫,在許多情況下,都可在「零設定」模式下使用。如需更新版 API 介面,請參閱說明文件

  • API 現在公開了 GenerateSWInjectManifest 兩種類別。這會讓使用者明確切換模式,與 v2 行為的切換則是根據 swSrc 的存在而變更。
  • 根據預設,系統會預先快取 Webpack 編譯管道中的資產,不再需要設定 globPatterns。如要繼續使用 globPatterns,唯一的原因是您需要預先快取未納入 Webpack 版本中的資產。一般而言,當您遷移至 v3 外掛程式時,請先移除先前的所有以 glob 為基礎的設定,並只在必要時重新加入。

取得協助

我們預期大部分的遷移作業都很簡單。如果您遇到本指南未涵蓋的問題,請在 GitHub 上建立問題告訴我們。