免安裝導覽體驗

將傳統預先擷取技術與服務工作處理程序搭配使用。

德米安 (Demián Renzulli)
Demián Renzulli
吉爾伯托‧科奇 (Gilberto Cocchi)
Gilberto Cocchi

在網站上執行工作通常包含數個步驟。舉例來說,在電子商務網站中購買產品,可能是搜尋產品、從結果清單中挑選商品、將商品加入購物車,以及完成結帳等作業。

就技術方面,在瀏覽不同網頁時意味著提出「瀏覽要求」。一般而言,您「不要」使用長期的 Cache-Control 標頭快取導覽要求的 HTML 回應。它們通常會透過網路 (和 Cache-Control: no-cache) 達成,確保 HTML 及後續網路要求鏈結 (合理) 保持最新狀態。因此,當使用者每次瀏覽新網頁時,都要連線至網路,代表每次瀏覽的速度都可能較慢,至少也表示網頁瀏覽的速度較慢。

如要加快處理要求,如果您預期使用者會採取的動作,可以事先要求這些網頁和素材資源,並將這些網頁和素材資源留在快取中一小段時間,直到使用者點擊這些連結為止。這項技術稱為「預先擷取」,一般來說是藉由將 <link rel="prefetch"> 標記加入網頁來實作,指示要預先擷取的資源。

本指南將介紹各種將 Service Worker 做為補充傳統預先擷取技術的做法。

正式環境

MercadoLibre 是拉丁美洲最大的電子商務網站。為加快瀏覽速度,這類解決方案會在流程的某些部分動態插入 <link rel="prefetch"> 標記。舉例來說,在資訊頁面中,當使用者捲動至清單底部時,就會擷取下一個結果網頁:

MercadoLibre 的商店資訊第一頁和兩頁,以及一個連結預先擷取代碼的 Link Prefetch 標記的螢幕截圖。

預先擷取檔案的優先順序為「最低」,並儲存在 HTTP 快取記憶體快取 (視資源是否可供快取而定),相關時間長度則視瀏覽器而定。例如,從 Chrome 85 開始,這個值是 5 分鐘。資源會保留五分鐘,之後將套用資源的一般 Cache-Control 規則。

使用 Service Worker 快取功能,可延長預先擷取資源的生命週期,範圍超過五分鐘的時間。

例如,義大利體育入口網站 Virgilio Sport 會透過服務工作人員預先擷取網站上最熱門的貼文。此外,他們也會使用 Network Information API,避免預先擷取 2G 連線使用者的內容。

Virgilio Sport 標誌。

因此,自從 Virgilio Sport 觀測到 3 週後,文章導覽載入時間縮短 78%,文章曝光次數則增加了 45%

Virgilio Sport 首頁和文章頁面的螢幕截圖,在預先擷取後影響指標。

使用 Workbox 實作預先快取

在下一節中,我們會使用 Workbox 示範如何在服務工作處理程序中實作不同的快取技術,並藉由將這項工作完全委派給服務工作人員來補充 <link rel="prefetch"> 或替代作業。

1. 預先快取靜態網頁和網頁子資源

預先快取可讓服務工作處理程序在安裝期間將檔案儲存到快取。

在以下情況中,預先快取的目的在於達到預先擷取的目標:加快瀏覽速度。

預先快取靜態網頁

針對在建構期間產生的網頁 (例如 about.htmlcontact.html) 或完全靜態網站所產生的網頁,可以將網站上的文件加入預先快取清單。如此一來,使用者每次存取這些文件時,即可在快取中存取這些內容:

workbox.precaching.precacheAndRoute([
  {url: '/about.html', revision: 'abcd1234'},
  // ... other entries ...
]);

預先快取頁面子資源

針對網站各部分可能使用的靜態素材資源 (例如 JavaScript、CSS 等) 預先快取靜態素材資源是通用的最佳做法,可針對預先擷取情境進行額外強化。

如要加快電子商務網站的瀏覽速度,您可以在產品資訊頁面中使用 <link rel="prefetch"> 標記,為產品資訊頁面中的前幾項產品預先擷取產品詳細資料頁面。如果您已預先快取產品頁面子資源,就能加快瀏覽速度。

如要實作這項功能,請按照下列步驟操作:

  • 為網頁加上 <link rel="prefetch"> 標記:
 <link rel="prefetch" href="/phones/smartphone-5x.html" as="document">
  • 將頁面子資源新增至 Service Worker 的預先快取清單:
workbox.precaching.precacheAndRoute([
  '/styles/product-page.ac29.css',
  // ... other entries ...
]);

2. 延長預先擷取資源的生命週期

如前文所述,<link rel="prefetch"> 會擷取並保留 HTTP 快取中的資源一段時間,之後便會套用資源的 Cache-Control 規則。在 Chrome 85 版中,這個值為 5 分鐘。

服務工作處理程序可讓您延長預先擷取網頁的生命週期,同時讓這些資源可供離線使用。

在上述範例中,您可以運用 Workbox 執行階段快取策略,來補充用於預先擷取產品網頁的 <link rel="prefetch">

如要實作這項功能,請按照下列步驟操作:

  • 為網頁加上 <link rel="prefetch"> 標記:
 <link rel="prefetch" href="/phones/smartphone-5x.html" as="document">
  • 在服務工作站中針對以下類型的要求實作執行階段快取策略:
new workbox.strategies.StaleWhileRevalidate({
  cacheName: 'document-cache',
  plugins: [
    new workbox.expiration.Plugin({
      maxAgeSeconds: 30 * 24 * 60 * 60, // 30 Days
    }),
  ],
});

在這種情況下,我們選擇採用過時的重新驗證策略。在這項策略中,系統可以同時從快取和網路要求網頁。回應來自快取 (如有),否則來自網路。每次成功要求時,快取都會與網路回應保持最新狀態。

3. 委派預先擷取至 Service Worker

在多數情況下,最好的做法是使用 <link rel="prefetch">。這個標記是一種資源提示,旨在盡可能提高預先擷取的效率。

但在某些情況下,最好將這項工作完全委派給服務工作站。 舉例來說,如要預先擷取用戶端轉譯產品資訊頁面中的前幾項產品,可能要依據 API 回應,在網頁中以動態方式插入多個 <link rel="prefetch"> 標記。這可能會暫時消耗網頁主執行緒上的時間,並導致實作困難。

在這種情況下,請使用「頁面至 Service Worker 通訊策略」,將預先擷取的工作完全委派給服務工作處理程序。您可以使用 worker.postMessage() 進行以下類型的通訊:

頁面圖示,用於與 Service Worker 進行雙向通訊。

Workbox Window 套件可簡化這類通訊,並將目前已完成的基本呼叫的許多細節摘要下來。

您可以按照以下方式,使用 Workbox 視窗預先擷取:

  • 在網頁上:呼叫 Service Worker,將訊息類型及要預先擷取的網址清單傳送給該服務:
const wb = new Workbox('/sw.js');
wb.register();

const prefetchResponse = await wb.messageSW({type: 'PREFETCH_URLS', urls: […]});
  • 在 Service Worker 中:實作訊息處理常式,為每個要預先擷取的網址發出 fetch() 要求:
addEventListener('message', (event) => {
  if (event.data.type === 'PREFETCH_URLS') {
    // Fetch URLs and store them in the cache
  }
});