NavigationPreloadManager
Baseline Widely available
This feature is well established and works across many devices and browser versions. It’s been available across browsers since April 2018.
安全なコンテキスト用: この機能は一部またはすべての対応しているブラウザーにおいて、安全なコンテキスト (HTTPS) でのみ利用できます。
メモ: この機能はウェブワーカー内で利用可能です。
NavigationPreloadManager
はサービスワーカー API のインターフェイスで、サービスワーカーによるリソースの事前読み込みを管理するためのメソッドを提供します。
対応していれば、この型のオブジェクトは ServiceWorkerRegistration.navigationPreload
によって返されます。
事前読み込みフェッチリクエストの結果は、FetchEvent.preloadResponse
によって返されたプロミスを使用して待ちます。
メソッド
解説
サービスワーカーは、指定されたスコープ内のページに対して、サイトの代理として fetch()
イベントを処理します。
ユーザーがサービスワーカーを使用するページに移動すると、ブラウザーは(まだ実行していなければ)ワーカーを起動し、フェッチイベントを送信して結果を待ちます。
イベントを受信すると、キャッシュにリソースが存在する場合はそれを返します。存在しない場合はリモートサーバーからリソースを取得します(将来のリクエストで返すためのコピーを保存します)。
サービスワーカーは、起動するまでブラウザーからのイベントを処理できません。 これは避けられませんが、通常は大きな影響はありません。 サービスワーカーは、多くの場合、すでに開始されています(他にもリクエストされた処理が完了する時点までアクティブな状態が続きます)。 サービスワーカーが起動しなければならない場合でも、多くの場合、キャッシュから値が返されるため、非常に高速です。 しかし、リモートリソースを取得し始める前にワーカーが起動しなければならない場合、遅延は著しくなる可能性があります。
NavigationPreloadManager
には、サービスワーカーの起動時にリソースを並列して取得するメカニズムが用意されており、これにより、ワーカーがブラウザーからのフェッチリクエストを処理できるまでに、リソースがすでに完全に、または部分的にダウンロードされている状態にすることができます。
これにより、ワーカーがすでに開始されている場合と「同程度」に悪い状態で開始される場合、場合によってはそれよりも良い状態で開始される場合があります。
事前読み込みマネージャーは、事前読み込みリクエストに HTTP の Service-Worker-Navigation-Preload
ヘッダーを送信し、事前読み込みリクエストに対するレスポンスをカスタマイズできるようにします。
例えば、元のページの一部だけに送信されるデータを削減したり、ユーザーのログイン状態に基づいてレスポンスをカスタマイズしたりするために使用できます。
例
この例は Speed up Service Worker with Navigation Preloads (developer.chrome.com) から取ったものです。
ナビゲーションの事前読み込みの機能を検出して有効化
下記では、最初の ServiceWorkerRegistration.navigationPreload
を使用して、この機能に対応してしているかどうかを判断した後、サービスワーカーの activate イベントハンドラーでナビゲーションの事前読み込みを有効にしています(この関数は、サービスワーカー用の NavigationPreloadManager
を返すか、機能に対応していない場合は undefined
を返します)。
addEventListener("activate", (event) => {
event.waitUntil(
(async () => {
if (self.registration.navigationPreload) {
// ナビゲーションの事前読み込みを有効にします!
await self.registration.navigationPreload.enable();
}
})(),
);
});
事前読み込みされたレスポンスの使用
次のコードは、事前読み込みされたレスポンス (FetchEvent.preloadResponse
) を使用するサービスワーカーのフェッチイベントハンドラーを示しています。
fetch
イベントハンドラーは、FetchEvent.respondWith()
を呼び出して、コントロールするページにプロミスを渡すと、このプロミスはリクエストされたリソースで解決されます。リソースは、キャッシュ、事前読み込みされたフェッチリクエスト、または新しいネットワークリクエストから取得されます。
この Cache
オブジェクトに一致する URL リクエストがある場合、コードはキャッシュからレスポンスを取得するための解決済みのプロミスを返します。
キャッシュに一致するものがなかった場合、コードは解決済みの事前読み込みレスポンス (FetchEvent.preloadResponse
) を返します。
一致するキャッシュ項目または事前読み込みレスポンスがなかった場合、コードはネットワークから新しい読み取り操作を開始し、その読み取り操作のための(未解決の)プロミスを返します。
addEventListener("fetch", (event) => {
event.respondWith(
(async () => {
// 可能なら、キャッシュから応答します
const cachedResponse = await caches.match(event.request);
if (cachedResponse) return cachedResponse;
// それがなく、事前読み込みされたレスポンスがあれば、それを使用します
const response = await event.preloadResponse;
if (response) return response;
// それもなければ、ネットワークを試します。
return fetch(event.request);
})(),
);
});
独自のレスポンス
ブラウザーは、事前読み込みリクエストに HTTP の Service-Worker-Navigation-Preload
ヘッダーを、既定で true
のディレクティブ値で送信します。
これにより、サーバーは通常のフェッチリクエストと事前読み込みフェッチリクエストを区別し、必要に応じてそれぞれ異なるレスポンスを送信することができます。
メモ:
事前読み込みと通常のフェッチ操作で異なるレスポンスを返すことができる場合、サーバーは確実に異なるレスポンスがキャッシュされるように Vary: Service-Worker-Navigation-Preload
を設定する必要があります。
NavigationPreloadManager.setHeaderValue()
を使用してヘッダー値を変更し、先読み操作に追加のコンテキストを提供することができます。
例えば、最近キャッシュされたリソースの ID を値として設定すると、サーバーは実際に必要とされるまでリソースを返さなくなります。
同様に、Cookie を使用する代わりに、認証ステータスに基づいて返値を構成することもできます。
下記のコードは、ヘッダーディレクティブの値を、変数 newValue
に設定する方法を示しています。
navigator.serviceWorker.ready
.then((registration) =>
registration.navigationPreload.setHeaderValue(newValue),
)
.then(() => {
console.log("Done!");
});
Speed up Service Worker with Navigation Preloads > Custom responses for preloads は、記事のウェブページのレスポンスがキャッシュされたヘッダーとフッターから構築されるサイトの、より完全な例を提供します。これにより、記事コンテンツのみが先読みされるように返されます。
状態の取得
NavigationPreloadManager.getState()
を使用すると、ナビゲーションの事前読み込みが有効になっているかどうかを調べ、事前読み込みリクエストに対して HTTP の Service-Worker-Navigation-Preload
ヘッダーにどのようなディレクティブ値が送信されているかを判断することができます。
下記コードは、状態オブジェクトに解決するプロミスを取得し、結果をログ出力する方法を示しています。
navigator.serviceWorker.ready
.then((registration) => registration.navigationPreload.getState())
.then((state) => {
console.log(state.enabled); // boolean
console.log(state.headerValue); // string
});
仕様書
Specification |
---|
Service Workers # navigation-preload-manager |
ブラウザーの互換性
BCD tables only load in the browser
関連情報
- Speed up Service Worker with Navigation Preloads (developer.chrome.com)