NavigationPreloadManager
注意:此功能在 Web Workers 中可用。
NavigationPreloadManager 介面是 Service Worker API 的一部分,它提供了用於在 Service Worker 啟動期間並行管理資源預載入的方法。
如果受支援,該型別的物件將透過 ServiceWorkerRegistration.navigationPreload 返回。預載入 fetch 請求的結果可以透過 FetchEvent.preloadResponse 返回的 Promise 來等待。
例項方法
-
設定在預載入請求中傳送的
Service-Worker-Navigation-PreloadHTTP 頭的的值,並返回一個空的Promise。 -
返回一個
Promise,該 Promise 解析為一個物件,其中包含指示預載入是否已啟用以及在預載入請求中Service-Worker-Navigation-PreloadHTTP 頭中將傳送什麼值的屬性。
描述
Service Worker 代表網站處理特定作用域內的頁面 fetch() 事件。當用戶導航到一個使用 Service Worker 的頁面時,瀏覽器會啟動該 Service Worker(如果它尚未執行),然後向其傳送一個 fetch 事件並等待結果。收到事件後,Worker 會在快取中查詢資源,如果找到則返回,否則從遠端伺服器獲取資源(並存儲一份以備將來請求使用)。
Service Worker 在啟動之前無法處理來自瀏覽器的事件。這是不可避免的,但通常影響不大。Service Worker 通常已經啟動(在處理其他請求後會保持活動一段時間)。即使 Service Worker 需要啟動,很多時候它也會從快取返回資料,這非常快。然而,在那些 Worker 需要在開始從遠端伺服器獲取資源之前啟動的情況下,延遲可能會很顯著。
NavigationPreloadManager 提供了一種機制,允許在 Service Worker 啟動的同時獲取資源,這樣,當 Worker 能夠處理來自瀏覽器的 fetch 請求時,資源可能已經完全或部分下載。這使得 Worker 啟動的情況“不比”Worker 已經啟動時更糟,有時甚至更好。
預載入管理器會在預載入請求中傳送 Service-Worker-Navigation-Preload HTTP 頭,允許響應針對預載入請求進行自定義。例如,這可以用來減少傳送到頁面的資料量,僅限於原始頁面的部分內容,或者根據使用者的登入狀態自定義響應。
示例
這裡的示例來自 使用導航預載入加速 Service Worker (developer.chrome.com)。
功能檢測和啟用導航預載入
在下面的示例中,我們在 Service Worker 的 activate 事件處理程式中啟用導航預載入。在此之前,我們首先使用 ServiceWorkerRegistration.navigationPreload 來確定該功能是否受支援(如果支援,它會返回 Service Worker 的 NavigationPreloadManager;如果不支援,則返回 undefined)。
addEventListener("activate", (event) => {
event.waitUntil(
(async () => {
if (self.registration.navigationPreload) {
// Enable navigation preloads!
await self.registration.navigationPreload.enable();
}
})(),
);
});
使用預載入的響應
以下程式碼展示了一個 Service Worker 的 fetch 事件處理程式,該程式使用預載入的響應(FetchEvent.preloadResponse)。
fetch 事件處理程式呼叫 FetchEvent.respondWith(),將一個 Promise 返回給受控頁面。這個 Promise 將會用請求的資源來解析,該資源可能來自快取、預載入的 fetch 請求或新的網路請求。
如果 Cache 物件中存在匹配的 URL 請求,則程式碼返回一個用於從快取獲取響應的已解析 Promise。如果快取中未找到匹配項,程式碼將返回已解析的預載入響應(FetchEvent.preloadResponse)。如果快取條目或預載入響應均未匹配,程式碼將啟動一個新的網路 fetch 操作,並返回該 fetch 操作的(未解析的)Promise。
addEventListener("fetch", (event) => {
event.respondWith(
(async () => {
// Respond from the cache if we can
const cachedResponse = await caches.match(event.request);
if (cachedResponse) return cachedResponse;
// Else, use the preloaded response, if it's there
const response = await event.preloadResponse;
if (response) return response;
// Else try the network.
return fetch(event.request);
})(),
);
});
自定義響應
瀏覽器在預載入請求時會發送 HTTP 頭 Service-Worker-Navigation-Preload,其預設指令值為 true。這允許伺服器區分正常 fetch 請求和預載入 fetch 請求,並在必要時傳送不同的響應。
注意:如果預載入和正常 fetch 操作的響應可能不同,那麼伺服器必須設定 Vary: Service-Worker-Navigation-Preload 來確保不同響應被正確快取。
可以使用 NavigationPreloadManager.setHeaderValue() 將頭的值更改為任何其他字串值,以便為預取操作提供額外的上下文。例如,您可以將值設定為您最近快取的資源的 ID,這樣伺服器就不會返回任何不需要的資源。同樣,您也可以根據身份驗證狀態配置返回的資訊,而不是使用 cookies。
以下程式碼演示瞭如何將頭指令的值設定為變數 newValue。
navigator.serviceWorker.ready
.then((registration) =>
registration.navigationPreload.setHeaderValue(newValue),
)
.then(() => {
console.log("Done!");
});
使用導航預載入加速 Service Worker > 預載入的自定義響應 提供了更完整的示例,其中一個文章網頁的響應由快取的頭部和尾部構建,因此在預取時僅返回文章內容。
獲取狀態
您可以使用 NavigationPreloadManager.getState() 來檢查導航預載入是否已啟用,並確定在預載入請求中 Service-Worker-Navigation-Preload HTTP 頭將傳送什麼指令值。
以下程式碼展示瞭如何獲取解析為 state 物件的 Promise 並記錄結果。
navigator.serviceWorker.ready
.then((registration) => registration.navigationPreload.getState())
.then((state) => {
console.log(state.enabled); // boolean
console.log(state.headerValue); // string
});
規範
| 規範 |
|---|
| Service Workers # navigation-preload-manager |
瀏覽器相容性
載入中…
另見
- 使用導航預載入加速 Service Worker (developer.chrome.com)