免安裝導覽體驗

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

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 偵測到文章導覽的載入時間超過 3 週,使文章導覽載入時間提升 78%,文章曝光次數則增加了 45%

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

使用 Workbox 實作預先快取

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

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

快取是指 Service Worker 在安裝期間,可以將檔案儲存到快取中。

在下列情況中,預先快取是用於達成與預先擷取相似的目標:加快瀏覽速度。

預先快取靜態網頁

如果是在建構時產生的網頁 (例如 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 分鐘。

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

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

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

  • 在網頁上新增 <link rel="prefetch"> 標記:
 <link rel="prefetch" href="/phones/smartphone-5x.html" as="document">
  • 在 Service Worker 中針對以下類型的要求實作執行階段快取策略:
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">。代碼是一種資源提示,目的是讓預先擷取能夠盡可能更有效率。

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

在這種情況下,請使用「對 Service Worker 的通訊策略」進行,將完全預先擷取的工作委派給服務工作人員。您可使用 worker.postMessage() 來達成此類通訊:

此圖示代表與服務工作處理程序進行雙向通訊的頁面。

工作箱視窗套件可簡化這種通訊方式,並提取正在進行的基礎呼叫的許多細節。

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