網路優先 HTML 的導覽預先載入功能

當 Service Worker 處理 fetch 事件時,瀏覽器會等候 Service Worker 提供回應。雖然網路要求延遲是等待過程的重要一環,但瀏覽器可能也必須等待 Service Worker 啟動並觸發 fetch 事件回呼。

開機時間會因裝置和功能而異,但相關時間可能相當長,在 CPU 速度緩慢時需要花費長達半秒,或是因環境條件而處於節流狀態。如果透過 Cache 執行個體提供導覽回應,不使用網路的效能改善程度可能會高於這個啟動時間。針對傳送至網路的導覽要求,導入 Service Worker 可建立可察覺的延遲。

輸入導覽預先載入

Navigation 預先載入是一項 Service Worker 功能,可以解決服務工作站啟動時間造成的延遲。在未啟用導覽預先載入功能的情況下,Service Worker 的啟動和處理的導覽要求都會連續發生:

黃色和藍色長條,兩個線段顯示連續動作。第一個是黃色的區段是「SW 啟動」,而藍色區段則是閱讀「Navigation request」(導覽要求) 的藍色區段。

這不是理想的做法,但只要啟用導覽預先載入功能即可解決這個問題,這樣可確保 Service Worker 系統會啟動並同時發生導覽要求:

兩條長條彼此堆疊,靠左對齊,代表兩個並行動作。黃色列標示為「SW 啟動」,藍色列則標示為「Navigation 要求」。

雖然導覽預先載入功能可為使用 Service Worker 的網站帶來最佳效能最佳化,但並非適用於所有情況的功能。請特別注意,使用預先快取應用程式殼層的網站不需要導覽預先載入,因為快取會提供應用程式殼層標記的瀏覽要求,而沒有任何瀏覽延遲。在這類情況下,預先載入的回應會浪費時間,成效不彰。

使用瀏覽預先載入功能的最佳時機,就是網站無法預先快取 HTML。想想哪些網站中的標記回應是動態的,會因驗證狀態等因素而不同。這些應用程式的導覽要求可能會使用以網路為優先 (甚至是僅限網路) 的策略,這時導覽預先載入功能就能大大不同。

在 Workbox 中使用導覽預先載入

在非由 Workbox 技術支援的 Service Worker 中直接使用導覽預先載入功能並不容易。首先,並非所有瀏覽器都支援這項功能。其二,要做出正確判斷並不容易。你可以參閱 Jake Archibald 撰寫的優質說明,瞭解如何直接使用這項工具。

Workbox 簡化了使用導覽預先載入程序,因為 workbox-navigation-preload 模組的 enable 方法會執行必要的功能支援檢查,以及建立 activate 事件監聽器來為您啟用。

由此可見,透過 Workbox 使用網路優先策略處理常式處理導覽要求,支援瀏覽器導入導覽預先載入功能的優點:

import * as navigationPreload from 'workbox-navigation-preload';
import {NetworkFirst, StaleWhileRevalidate} from 'workbox-strategies';
import {registerRoute, NavigationRoute, Route} from 'workbox-routing';
import {precacheAndRoute} from 'workbox-precaching';

// Precache the manifest
precacheAndRoute(self.__WB_MANIFEST);

// Enable navigation preload
navigationPreload.enable();

// Create a new navigation route that uses the Network-first, falling back to
// cache strategy for navigation requests with its own cache. This route will be
// handled by navigation preload. The NetworkOnly strategy will work as well.
const navigationRoute = new NavigationRoute(new NetworkFirst({
  cacheName: 'navigations'
}));

// Register the navigation route
registerRoute(navigationRoute);

// Create a route for image, script, or style requests that use a
// stale-while-revalidate strategy. This route will be unaffected
// by navigation preload.
const staticAssetsRoute = new Route(({request}) => {
  return ['image', 'script', 'style'].includes(request.destination);
}, new StaleWhileRevalidate({
  cacheName: 'static-assets'
}));

// Register the route handling static assets
registerRoute(staticAssetsRoute);

啟用導覽預先載入功能後,Workbox 會回應使用 NetworkFirstNetworkOnly 策略的瀏覽要求,並提供預先載入的回應。

如何判斷瀏覽預先載入功能是否正常運作?

開發建構作業中,Workbox 會記錄功能。如要檢查 Workbox 的預先載入功能是否正常運作,請在瀏覽要求期間透過支援的瀏覽器開啟控制台,然後就會看到記錄訊息 (包括:

Chrome 開發人員工具控制台的 Workbox 記錄螢幕截圖。訊息由上到下顯示:「路由器正在回應 /」、「使用預先載入的導覽要求 / 」和「使用 NetworkFirst 回應 /」

根據預設,實際工作環境版本不會顯示這項記錄功能,因此在將 Service Worker 部署至實際工作環境時不會顯示,但這是驗證導覽預先載入功能是否正常運作的好方法 (以及其他項目)。

自訂預先載入的回應

使用導覽預先載入功能時,在某些情況下,您需要自訂應用程式後端的預先載入回應。從網路串流部分內容的服務工作站是可能派上用場的情況。

在這類情況下,系統會知道系統會透過設定 Service-Worker-Navigation-Preload 標頭且設定預設值 true 傳送預先載入要求:

Service-Worker-Navigation-Preload: true

接著,您可以在所選的應用程式後端中檢查這個標頭,並視需求修改回應。如果標頭的預設值因任何原因而造成問題,您可以在視窗內容中變更。請注意,您在伺服器上為了讀取這個標頭所進行的任何工作,由您自行決定,不在 Workbox 範圍內。

結語

直接使用瀏覽功能難以正確取得,但這個步驟值得一提,確保服務工作處理程序不會讓瀏覽器造成瀏覽器發出瀏覽要求。多虧了 Workbox,您能夠以更少的工夫,享有預先載入的導覽功能。如要進一步瞭解 workbox-navigation-preload 模組,請參閱其參考說明文件