ServiceWorkerGlobalScope: fetch イベント
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) でのみ利用できます。
メモ: この機能はサービスワーカー内でのみ利用可能です。
fetch
は ServiceWorkerGlobalScope
インターフェイスのイベントで、メインアプリスレッドがネットワークリクエストを発行したときに、サービスワーカーのグローバルスコープで発生します。これにより、サービスワーカーがネットワークリクエストを傍受し、独自のレスポンス(例えば、ローカルキャッシュからのレスポンス)を送信できるようになります。
このイベントはキャンセル不可で、バブリングしません。
構文
このイベント名を addEventListener()
等のメソッドで使用するか、イベントハンドラープロパティを設定するかしてください。
addEventListener("fetch", (event) => {});
onfetch = (event) => {};
解説
この fetch
イベントは、メインスレッドがネットワークリクエストを行う際に、サービスワーカーのグローバルスコープで発生します。これはメインスレッドからの明示的な fetch()
呼び出しだけではなく、ページナビゲーションや JavaScript、CSS、画像などのリソースの取得による暗黙的なリクエストでも発生します。
イベントハンドラーは FetchEvent
オブジェクトを受け取り、Request
インスタンスを通じてリクエストにアクセスできます。
FetchEvent
はパラメーターに Response
、または Response
で解決する Promise
を受け取る respondWith()
メソッドを持っています。これにより、サービスワーカーのイベントハンドラーはメインスレッドでリクエストに返されるレスポンスを差し替えることができます。
例えばサービスワーカーは以下のような値へ差し替えることができます。
Cache
インターフェイスから取得したレスポンスのローカルキャッシュResponse.json()
やResponse()
コンストラクターなどのメソッドでサービスワーカーが合成したレスポンス。Response.error()
による ネットワークエラー。これはfetch()
呼び出しを拒否させます。
respondWith()
メソッドは、一つのリクエストに対して一度だけ呼び出すことができます。複数の fetch
イベントリスナーが設定された場合、respondWith()
が呼び出されるまで、登録された順に呼び出されます。
respondWith()
メソッドは同期的に呼び出す必要があります。つまり then
ハンドラーから呼び出すことはできません。
通常、fetch
イベントハンドラーは URL などのリクエスト特徴に応じて異なる戦略をとります。
function strategy1() {
return fetch("picnic.jpg");
}
function strategy2() {
return Response.error();
}
const pattern1 = /^\/salamander/;
const pattern2 = /^\/lizard/;
self.addEventListener("fetch", (event) => {
const url = new URL(event.request.url);
if (pattern1.test(url.pathname)) {
event.respondWith(strategy1());
} else if (pattern2.test(url.pathname)) {
event.respondWith(strategy2());
}
});
ハンドラー内で respondWith()
が呼び出されなかった場合、ユーザーエージェントは自動的に元のネットワークリクエストを行います。例えば上記のコードでは pattern1
または pattern2
にマッチしないリクエストはすべて、サービスワーカーが存在しなかったかのように振る舞います。
イベント型
FetchEvent
です。
例
キャッシュからネットワークへのフォールバック
この fetch
イベントハンドラーは、まずキャッシュ済みのレスポンスを探します。レスポンスが見つかった場合はキャッシュ済みのレスポンスを返します。そうでない場合はネットワークからリソースを取得しようとします。
async function cacheThenNetwork(request) {
const cachedResponse = await caches.match(request);
if (cachedResponse) {
console.log("Found response in cache:", cachedResponse);
return cachedResponse;
}
console.log("Falling back to network");
return fetch(request);
}
self.addEventListener("fetch", (event) => {
console.log(`Handling fetch event for ${event.request.url}`);
event.respondWith(cacheThenNetwork(event.request));
});
キャッシュのみ
この fetch
イベントハンドラーは、スクリプトとスタイルシートに対して「キャッシュのみ」ポリシーを実装します。リクエストの destination
が "script"
または "style"
である場合、ハンドラーはキャッシュだけを探し、レスポンスが見つからない場合はエラーを返します。その他のリクエストはすべてネットワークを通して行われます。
async function cacheOnly(request) {
const cachedResponse = await caches.match(request);
if (cachedResponse) {
console.log("Found response in cache:", cachedResponse);
return cachedResponse;
}
return Response.error();
}
self.addEventListener("fetch", (event) => {
if (
event.request.destination === "script" ||
event.request.destination === "style"
) {
event.respondWith(cacheOnly(event.request));
}
});
仕様書
Specification |
---|
Service Workers # dom-serviceworkerglobalscope-onfetch |
ブラウザーの互換性
BCD tables only load in the browser
関連情報
- サービスワーカーの使用
- サービスワーカーの基本的なコード例
fetch()
メソッドRequest
インターフェイスResponse
インターフェイス