FetchEvent.respondWith()

respondWith()FetchEvent インターフェイスのメソッドで、ブラウザー既定の fetch 処理を抑止して、自分自身で Response 用のプロミスを提供できるようにします。

たいていの場合、受信者が理解できるどんなレスポンスでも提供できます。例えば、<img> がリクエストを開始した場合、レスポンス本体には画像データが必要です。セキュリティの理由から、グローバルルールが少しあります。

  • type が "opaque" (不透明)の Response オブジェクトを返すことができるのは、 fetchEvent.request オブジェクトの mode が "no-cors" の場合だけです。これはプライベートなデータの漏洩を防ぎます。
  • type が "opaqueredirect" (不透明なリダイレクト)の Response オブジェクトを返すことができるのは、fetchEvent.request オブジェクトの mode が "manual" の場合だけです。
  • fetchEvent.request オブジェクトの mode が "same-origin" の場合、type が "cors" の Response オブジェクトを返すことはできません。

リソースの最終 URL を指定する

Firefox 59 以降、サービスワーカーが FetchEvent.respondWith()Response を提供すると、Response.url 値は最終的に解決された URL として、ネットワークリクエストに介入する際に伝搬されるようになりました。Response.url 値が空文字列の場合は、FetchEvent.request.url が最終的な URL として使用されます。

かつては FetchEvent.request.url がすべての場合に最終 URL として使われていました。与えられた Response.url は実際には無視されていました。

つまり、例えば、サービスワーカーがスタイルシートやワーカースクリプトに介入すると、与えられた Response.url が、サブリソースが読み込む相対的な @importimportScripts() の代わりに使われます (Firefox バグ 1222008)。

たいていのネットワークリクエストに対して、最終 URL を観測できないためこの変更は影響ありません。しかし、少しだけ関係する場合があります。

  • fetch() が介入された場合、結果の Response.url で最終 URL を観測できます。
  • ワーカースクリプトが介入された場合、最終 URL は self.location をセットするのに使われ、ワーカースクリプトの相対 URL の代わりのベース URL として使われます。
  • スタイルシートが介入された場合、最終 URL は相対的な @import 読み込みの代わりのベース URL として使われます。

Windowiframe のナビゲーションリクエストはこの最終 URL を使わ「ない」ことに注意してください。HTML 仕様のナビゲーションのリダイレクトの処理方法では、Window.location のためにリクエスト URL を使います。これは、オフラインの時に、ユーザーに見える URL を変更することなくサイトが「代替の」ウェブページを提供できるということを意味します。

構文

js
respondWith(response)

引数

response

Response または Response に解決される Promise。それ以外の場合は、ネットワークエラーがフェッチ元に返されます。

返値

なし (undefined)。

例外

NetworkError DOMException

上記の「グローバルルール」にヒントがあるように、ネットワークエラーは FetchEvent.request.modeResponse.type の値の組み合わせで起動されます。

InvalidStateError DOMException

イベントが配信されていないか、respondWith() が既に呼び出されています。

この fetch イベントはキャッシュ API からのレスポンスを返そうとし、ない場合にはネットワークにフォールバックします。

js
addEventListener("fetch", (event) => {
  // 既定の動作を抑止し、リクエストを自分で処理します。
  event.respondWith(
    (async () => {
      // キャッシュからレスポンスを取得しようとします。
      const cachedResponse = await caches.match(event.request);
      // 見つかったらそれを返します。
      if (cachedResponse) return cachedResponse;
      // キャッシュ内に一致するものが見つからなかった場合は、ネットワークを使用します。
      return fetch(event.request);
    })(),
  );
});

メモ: caches.match() は便利なメソッドです。同等の機能は、cache.match() をそれぞれのキャッシュに対して(caches.keys() が返す順に)Response が返ってくるまで呼び出すことです。

仕様書

Specification
Service Workers
# fetch-event-respondwith

ブラウザーの互換性

BCD tables only load in the browser

関連情報