免安裝導覽體驗

將傳統的預先擷取技術與服務工作人員相輔相成。

Demián Renzulli
Demián Renzulli
Gilberto Cocchi
Gilberto Cocchi

在網站上執行工作通常需要幾個步驟。舉例來說,在電子商務網站上購買產品時,可能會用到搜尋產品、從結果清單中挑選商品、將商品加入購物車,以及完成結帳。

從技術層面來說,瀏覽不同頁面就等於發出導覽要求。一般來說,您不應使用長效 Cache-Control 標頭,為導覽要求快取 HTML 回應。這些要求通常會透過 Cache-Control: no-cache 的網路回應,確保 HTML 和後續網路要求鏈 (合理) 都是最新的。使用者每次瀏覽至新網頁時,都必須先連上網路,因此每次瀏覽的速度可能會變慢;如果甚至,則表示瀏覽速度不「穩定」

為了加快處理速度,如果您能預測使用者的動作,就可以提前要求這些網頁和資產,並保留在快取中一小段時間,直到使用者點選這些連結為止。這種做法稱為「預先載入」,通常會在網頁中加入 <link rel="prefetch"> 標記,指出要預先載入的資源。

在本指南中,我們將探討服務工作者可用於補足傳統預先擷取技術的各種方式。

實際工作環境案例

MercadoLibre 是拉丁美洲最大的電子商務網站。為了加快導覽速度,這些程式會在流程的部分部分動態插入 <link rel="prefetch"> 標記。舉例來說,在資訊頁面中,只要使用者捲動到資訊底部,系統就會擷取下一頁的結果:

MercadoLibre 列出頁面一和二的螢幕截圖,以及連結兩者的 Link Prefetch 代碼。

預先擷取的檔案會以「最低」優先順序要求,並儲存在 HTTP 快取記憶體快取中 (視資源是否可快取而定),時間長短視瀏覽器而定。舉例來說,在 Chrome 85 中,這個值為 5 分鐘。資源會保留五分鐘,之後就會套用資源的一般 Cache-Control 規則。

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

舉例來說,義大利體育網站 Virgilio Sport 使用服務工作者,在首頁預先擷取最熱門的貼文。他們也會使用 Network Information API,避免為使用 2G 連線的使用者預先載入。

Virgilio Sport 標誌。

因此,在觀察了 3 週後,Virgilio Sport 的文章導覽載入時間改善了 78%,文章曝光次數也增加了 45%

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

使用 Workbox 實作預先快取

在下一節中,我們將使用 Workbox 示範如何在 Service Worker 中實作不同的快取技術,這些技術可以用來輔助 <link rel="prefetch"> 或甚至取代 API,也就是將這項工作完全委派給服務工作站。

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
    }),
  ],
});

在本例中,我們選擇使用「Stale-while-revalidate」策略。在這種策略中,系統可以同時從快取和網路要求網頁。回應來自快取 (如有),否則來自網路。每次成功發出要求時,快取一律會與網路回應保持一致。

3. 將預先擷取作業委派給 Service Worker

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

不過,在某些情況下,將這項工作完全委派給服務工作可能會比較好。舉例來說,如要在用戶端算繪的產品資訊頁面中預先擷取前幾項產品,可能需要根據 API 回應,在頁面中動態插入多個 <link rel="prefetch"> 標記。這可能會暫時耗用網頁主執行緒的時間,並使實作更加困難。

在這種情況下,請使用「網頁與服務工作者通訊策略」,將預先載入的任務完全委派給服務工作者。您可使用 worker.postMessage() 來達成此類通訊:

與服務工作員進行雙向通訊的網頁圖示。

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
  }
});