漸進式網頁應用程式:使用 Workbox

1. 歡迎

在本實驗室中,您將使用現有的 Service Worker 轉換網站,並改用 Workbox。這是漸進式網頁應用程式研討會的一系列配套程式碼研究室中的第二個。先前的程式碼研究室是「離線」。本系列還有六個程式碼研究室。

課程內容

  • 將現有的 Service Worker 轉換為使用 Workbox
  • 在 PWA 中新增離線備用項目

注意事項

  • 基本 HTML 和 JavaScript

軟硬體需求

2. 開始設定

首先,請複製或下載完成本程式碼研究室所需的範例程式碼:

如果複製存放區,請確認您位於 pwa03--workbox 分支版本中。ZIP 檔案也包含該分支版本的程式碼。

這個程式碼集需要 Node.js 14 以上版本。取得程式碼後,請在程式碼資料夾中從指令列執行 npm ci,安裝所有需要的依附元件。接著執行 npm start,啟動本程式碼研究室的開發伺服器。

原始碼的 README.md 檔案會說明所有發布的檔案。此外,您在本程式碼研究室中會使用下列主要現有檔案:

金鑰檔案

  • service-worker.js - 應用程式的 Service Worker 檔案
  • offline.html - 網頁無法使用時的離線 HTML

3. 遷移至 Workbox

查看現有的 Service Worker,預先快取似乎可以分為兩個步驟:

  • 在 Service Worker 安裝期間快取相關檔案
  • 再次使用「僅限快取」策略提供這些檔案

index.html 檔案和 / 路由仍適合預先快取,因為這個網頁應用程式的 HTML 不會有太大變化,但 CSS 和 JavaScript 等其他檔案可能會變更,我們不希望每次變更時都必須經歷整個 Service Worker 生命週期。此外,目前的 Service Worker 只會考量部分 CSS 和 JavaScript,我們希望涵蓋所有內容。使用「過時重新驗證」策略快取這些項目會更有意義,因為這樣可以快速回應,並視需要於背景更新。

重新探討預先快取

遷移至 Workbox 時,我們不需要保留任何現有程式碼,因此請刪除 service-worker.js 中的所有內容。在上一個實驗室中,我們已設定要編譯的 Service Worker,因此可以在這裡使用 ESModule Imports,從 NPM 模組匯入 Workbox。首先,我們來複習預先快取。在 service-worker.js 中新增下列程式碼:

import { warmStrategyCache } from 'workbox-recipes';
import { CacheFirst } from 'workbox-strategies';
import { registerRoute } from 'workbox-routing';
import { CacheableResponsePlugin } from 'workbox-cacheable-response';
import { ExpirationPlugin } from 'workbox-expiration';

// Set up page cache
const pageCache = new CacheFirst({
  cacheName: 'page-cache',
  plugins: [
    new CacheableResponsePlugin({
      statuses: [0, 200],
    }),
    new ExpirationPlugin({
      maxAgeSeconds: 30 * 24 * 60 * 60,
    }),
  ],
});

warmStrategyCache({
  urls: ['/index.html', '/'],
  strategy: pageCache,
});

registerRoute(({ request }) => request.mode === 'navigate', pageCache);

說明

如要為 /index.html/ 設定預先快取,請從下列五個模組中提取。雖然這看起來很多,但這段程式碼比先前編寫的程式碼強大許多。

首先,請設定新的「快取優先」快取策略,選擇這個策略而非「僅限快取」策略,以便視需要將其他網頁加入快取。並命名為 page-cache。Workbox 策略可以採用多個外掛程式,這些外掛程式會影響從快取儲存及擷取內容的生命週期。這裡使用 Cacheable Response 外掛程式和 Expiration 外掛程式,確保只快取良好的伺服器回應,且快取中的每個項目都會在 30 天後清除。

接著,使用溫暖策略快取 Workbox 食譜,以 /index.html/ 溫暖策略快取。這樣一來,在 Service Worker 的安裝事件期間,這些項目就會新增至這個快取。

最後,系統會註冊新路徑。凡是網頁導覽要求,都會由這個「快取優先」策略管理,從快取或網路中提取,然後快取回應。

快取素材資源

解決路徑預先快取問題後,現在要重新實作網站資產 (CSS 和 JavaScript) 的快取功能。如要這麼做,請先將 StaleWhileRevalidate 新增至 workbox-strategies 匯入項目,然後在 Service Worker 的底部新增下列程式碼:

// Set up asset cache
registerRoute(
  ({ request }) => ['style', 'script', 'worker'].includes(request.destination),
  new StaleWhileRevalidate({
    cacheName: 'asset-cache',
    plugins: [
      new CacheableResponsePlugin({
        statuses: [0, 200],
      }),
    ],
  }),
);

說明

這條路徑會先判斷要求類型是樣式、指令碼還是工作站,分別對應 CSS、JavaScript 或 Web Worker。如果是,系統會使用「過時內容重新驗證」策略,先嘗試從快取提供服務,如果無法提供服務,則會改用網路,同時盡可能從網路更新快取中的版本。與網頁策略相同,這項策略只會快取良好回應。

4. 新增離線備用項

將原始 Service Worker 遷移至 Workbox 後,還有一件事需要完成,才能防止 PWA 在離線時當機,那就是新增離線備援。

您可以為離線時可能無法使用的任何內容設定離線備援,例如網頁、字型、CSS、JavaScript、圖片等。至少應為所有 PWA 設定網頁後備機制,這樣一來,如果使用者前往不在快取中的網頁,就會留在應用程式的環境中。

Workbox 方案提供離線備用方案,可用於執行這項操作!如要使用這項功能,請先將 offlineFallback 新增至 workbox-recipes 匯入項目,然後將下列程式碼新增至 Service Worker 的底部:

// Set up offline fallback
offlineFallback({
  pageFallback: '/offline.html',
});

說明

離線備用食譜會設定「僅限快取」策略,並使用提供的備用廣告預先載入。接著,系統會設定 Workbox 預設擷取處理常式,擷取任何失敗的路由要求 (如果快取中沒有任何內容,且無法透過網路存取任何內容),從快取中提取相關檔案的內容,並在要求持續失敗時將其做為內容傳回。

5. 恭喜!

您已瞭解如何使用 Workbox 為路徑設定快取策略,並為 PWA 提供離線備援。

本系列下一個程式碼研究室是 IndexedDB