Service Worker キャッシュと HTTP キャッシュ

Service Worker キャッシュと HTTP キャッシュ レイヤで一貫した有効期限ロジックを使用する場合と、異なる有効期限ロジックを使用する場合のメリットとデメリット。

Jonathan Chen
Jonathan Chen

サービス ワーカーと PWA が最新のウェブ アプリケーションの標準になりつつある一方で、リソース キャッシュ保存はこれまで以上に複雑になっています。この記事では、ブラウザ キャッシュの概要について説明します。

  • Service Worker キャッシュと HTTP キャッシュのユースケースと違い。
  • 通常の HTTP キャッシュ保存戦略と比較した、さまざまなサービス ワーカー キャッシュ保存期限戦略のメリットとデメリット。

キャッシュ フローの概要

ブラウザがリソースをリクエストする際、大まかに次のキャッシュ保存順序に従います。

  1. Service Worker キャッシュ: Service Worker は、リソースがキャッシュにあるかどうかを確認し、プログラムされたキャッシュ保存戦略に基づいてリソース自体を返すかどうかを決定します。なお、この処理は自動的には行われません。Service Worker で fetch イベント ハンドラを作成し、ネットワーク リクエストをインターセプトして、リクエストがネットワークではなく Service Worker のキャッシュから提供されるようにする必要があります。
  2. HTTP キャッシュ(ブラウザ キャッシュとも呼ばれます): リソースが HTTP キャッシュにあり、まだ有効期限が切れていない場合、ブラウザは HTTP キャッシュからリソースを自動的に使用します。
  3. サーバーサイド: Service Worker キャッシュまたは HTTP キャッシュに何も見つからない場合、ブラウザはネットワークにアクセスしてリソースをリクエストします。リソースが CDN にキャッシュ保存されていない場合、リクエストは配信元サーバーまで戻る必要があります。

キャッシュ保存フローの概要のイラスト。

キャッシュ レイヤ

Service Worker のキャッシュ保存

Service Worker はネットワーク タイプの HTTP リクエストをインターセプトし、キャッシュ保存戦略を使用して、ブラウザに返すリソースを決定します。サービス ワーカーのキャッシュと HTTP キャッシュは同じ一般的な目的を果たしますが、サービス ワーカーのキャッシュは、キャッシュに保存する内容やキャッシュ保存の方法をきめ細かく制御するなど、より多くのキャッシュ保存機能を提供します。

Service Worker のキャッシュを制御する

Service Worker は、イベント リスナー(通常は fetch イベント)で HTTP リクエストをインターセプトします。このコード スニペットは、キャッシュ ファーストのキャッシュ保存戦略のロジックを示しています。

サービス ワーカーが HTTP リクエストをインターセプトする仕組みを示す図。

Workbox を使用して、車輪の再発明を避けることを強くおすすめします。たとえば、1 行の正規表現コードでリソース URL パスを登録できます。

import {registerRoute} from 'workbox-routing';

registerRoute(new RegExp('styles/.*\\.css'), callbackHandler);

Service Worker のキャッシュ保存戦略とユースケース

次の表に、一般的な Service Worker のキャッシュ保存戦略と、各戦略が役立つ場合を示します。

戦略 鮮度に関する根拠 ユースケース
ネットワークのみ コンテンツは常に最新の状態である必要があります。
  • お支払いと購入手続き
  • 残高明細
ネットワークがキャッシュにフォールバックしている 新しいコンテンツを配信することをおすすめします。ただし、ネットワークに障害が発生した場合や、ネットワークが不安定な場合は、少し古いコンテンツを配信しても構いません。
  • タイムリーなデータ
  • 価格と料金(免責条項が必要)
  • 注文ステータス
Stale-while-revalidate キャッシュに保存されたコンテンツをすぐに提供しても構いませんが、今後更新されたキャッシュに保存されたコンテンツを使用する必要があります。
  • ニュース フィード
  • 商品リスティング ページ
  • メッセージ
キャッシュを優先し、ネットワークにフォールバックする コンテンツは重要ではなく、パフォーマンス向上のためにキャッシュから配信できますが、Service Worker は更新を定期的に確認する必要があります。
  • アプリシェル
  • 共通リソース
キャッシュのみ コンテンツはめったに変更されません。
  • 静的コンテンツ

サービス ワーカー キャッシュのその他のメリット

Service Worker のキャッシュ保存では、キャッシュ保存ロジックをきめ細かく制御できるだけでなく、次のことも可能です。

  • オリジン用のメモリとストレージ容量の増加: ブラウザは、オリジンごとに HTTP キャッシュ リソースを割り当てます。つまり、複数のサブドメインがある場合、それらはすべて同じ HTTP キャッシュを共有します。オリジン/ドメインのコンテンツが HTTP キャッシュに長期間保持される保証はありません。たとえば、ユーザーがブラウザの設定 UI から手動でクリーンアップしたり、ページでハード再読み込みをトリガーしたりして、キャッシュを削除することがあります。Service Worker キャッシュを使用すると、キャッシュに保存されたコンテンツがキャッシュに保存されたままになる可能性が大幅に高まります。詳細については、永続ストレージをご覧ください。
  • ネットワークの不安定さやオフライン エクスペリエンスに対する柔軟性の向上: HTTP キャッシュでは、リソースをキャッシュに保存するかどうかという 2 つの選択肢しかありません。Service Worker のキャッシュ保存を使用すると、(「stale-while-revalidate」戦略を使用して)小さな「ヒカップ」を簡単に軽減したり、(「Cache only」戦略を使用して)完全なオフライン エクスペリエンスを提供したり、必要に応じて(「Set catch handler」戦略を使用して)ページの一部を Service Worker のキャッシュから取得し、一部を除外したカスタマイズされた UI などの中間的なものを提供したりできます。

HTTP キャッシュ保存

ブラウザがウェブページと関連リソースを初めて読み込むとき、これらのリソースは HTTP キャッシュに保存されます。通常、HTTP キャッシュはブラウザによって自動的に有効になります。ただし、エンドユーザーが明示的に無効にしている場合は除きます。

HTTP キャッシュ保存を使用すると、リソースをキャッシュ保存するタイミングと期間をサーバーが決定します。

HTTP レスポンス ヘッダーで HTTP キャッシュの有効期限を制御する

サーバーがリソースに対するブラウザのリクエストに応答するとき、サーバーは HTTP レスポンス ヘッダーを使用して、リソースをキャッシュに保存する期間をブラウザに伝えます。詳しくは、レスポンス ヘッダー: ウェブサーバーを設定するをご覧ください。

HTTP キャッシュ保存戦略とユースケース

HTTP キャッシュ保存は、時間ベース(TTL)のリソース有効期限ロジックのみを扱うため、Service Worker キャッシュ保存よりもはるかに単純です。HTTP キャッシュ保存戦略の詳細については、どのレスポンス ヘッダー値を使用すべきか?HTTP キャッシュで不要なネットワーク リクエストを防ぐ(概要)をご覧ください。

キャッシュの有効期限ロジックを設計する

このセクションでは、Service Worker キャッシュと HTTP キャッシュのレイヤで一貫した有効期限ロジックを使用する場合のメリットとデメリット、およびこれらのレイヤで別々の有効期限ロジックを使用する場合のメリットとデメリットについて説明します。

すべてのキャッシュレイヤで一貫した有効期限ロジック

メリットとデメリットを説明するために、長期、中期、短期の 3 つのシナリオを見てみましょう。

シナリオ 長期キャッシュ保存 中期間のキャッシュ保存 短期キャッシュ保存
Service Worker のキャッシュ保存戦略 キャッシュ、ネットワークにフォールバック stale-while-revalidate ネットワークがキャッシュにフォールバックしている
Service Worker のキャッシュ TTL 30 days 1 日 10 分
HTTP キャッシュの max-age 30 days 1 日 10 分

シナリオ: 長期キャッシュ保存(キャッシュ、ネットワークへのフォールバック)

  • キャッシュに保存されたリソースが有効な場合(30 日以内): Service Worker はネットワークにアクセスせずに、キャッシュに保存されたリソースをすぐに返します。
  • キャッシュに保存されたリソースの有効期限が切れた場合(30 日以上経過した場合): Service Worker はネットワークにアクセスしてリソースを取得します。ブラウザの HTTP キャッシュにリソースのコピーがないため、ブラウザはサーバーサイドでリソースを取得します。

デメリット: このシナリオでは、Service Worker でキャッシュが期限切れになるとブラウザは常にリクエストをサーバーサイドに渡すため、HTTP キャッシュの価値は低くなります。

シナリオ: 中期キャッシュ保存(Stale-while-revalidate)

  • キャッシュに保存されたリソースが有効な場合(1 日以内): Service Worker はキャッシュに保存されたリソースをすぐに返し、ネットワークにアクセスしてリソースを取得します。ブラウザの HTTP キャッシュにリソースのコピーがあるため、そのコピーを Service Worker に返します。
  • キャッシュに保存されたリソースの有効期限が切れている場合(1 日以上経過している場合): Service Worker はキャッシュに保存されたリソースをすぐに返し、ネットワークにアクセスしてリソースを取得します。ブラウザの HTTP キャッシュにリソースのコピーがないため、サーバーサイドに移動してリソースを取得します。

短所: Service Worker は、「再検証」ステップを最大限に活用するために、HTTP キャッシュをオーバーライドする追加のキャッシュ無効化を必要とします。

シナリオ: 短期キャッシュ保存(ネットワークがキャッシュにフォールバック)

  • キャッシュに保存されたリソースが有効な場合(10 分以内): Service Worker はネットワークにアクセスしてリソースを取得します。ブラウザの HTTP キャッシュにリソースのコピーがあるため、サーバーサイドにアクセスせずに Service Worker にそのコピーを返します。
  • キャッシュに保存されたリソースの有効期限が切れている場合(10 分以上経過している場合): Service Worker はキャッシュに保存されたリソースを直ちに返し、ネットワークにアクセスしてリソースを取得します。ブラウザの HTTP キャッシュにリソースのコピーがないため、サーバーサイドに移動してリソースを取得します。

短所: 中期的なキャッシュ保存のシナリオと同様に、Service Worker は、サーバーサイドから最新のリソースを取得するために、HTTP キャッシュをオーバーライドする追加のキャッシュ無効化ロジックを必要とします。

すべてのシナリオでの Service Worker

どのシナリオでも、ネットワークが不安定な場合は、Service Worker のキャッシュからキャッシュに保存されたリソースを返すことができます。一方、ネットワークが不安定な場合やダウンしている場合、HTTP キャッシュは信頼できません。

Service Worker キャッシュと HTTP レイヤで異なるキャッシュ有効期限ロジック

メリットとデメリットを説明するために、長期、中期、短期のシナリオを再度見てみましょう。

シナリオ 長期キャッシュ保存 中期間のキャッシュ保存 短期キャッシュ保存
Service Worker のキャッシュ保存戦略 キャッシュ、ネットワークにフォールバック stale-while-revalidate ネットワークがキャッシュにフォールバックしている
Service Worker のキャッシュ TTL 90 日間 30 days 1 日
HTTP キャッシュの max-age 30 days 1 日 10 分

シナリオ: 長期キャッシュ保存(キャッシュ、ネットワークへのフォールバック)

  • キャッシュに保存されたリソースが Service Worker キャッシュで有効な場合(90 日以内): Service Worker はキャッシュに保存されたリソースを直ちに返します。
  • Service Worker のキャッシュでキャッシュに保存されたリソースの有効期限が切れた場合(90 日超): Service Worker はネットワークにアクセスしてリソースを取得します。ブラウザの HTTP キャッシュにリソースのコピーがないため、サーバーサイドに移動します。

長所と短所:

  • メリット: Service Worker がキャッシュに保存されたリソースをすぐに返すため、ユーザーは即座にレスポンスを受け取ることができます。
  • メリット: Service Worker は、キャッシュを使用するタイミングとリソースの新しいバージョンをリクエストするタイミングをより細かく制御できます。
  • デメリット: Service Worker のキャッシュ保存戦略を明確に定義する必要があります。

シナリオ: 中期キャッシュ保存(Stale-while-revalidate)

  • キャッシュに保存されたリソースが Service Worker のキャッシュで有効な場合(30 日以内): Service Worker はキャッシュに保存されたリソースを直ちに返します。
  • サービス ワーカー キャッシュ内のキャッシュに保存されたリソースの有効期限が切れた場合(30 日以上経過した場合): サービス ワーカーはリソースをネットワークに取得しに行きます。ブラウザの HTTP キャッシュにリソースのコピーがないため、サーバーサイドに移動します。

長所と短所:

  • メリット: Service Worker がキャッシュに保存されたリソースをすぐに返すため、ユーザーは即座にレスポンスを受け取ることができます。
  • メリット: Service Worker は、バックグラウンドで発生する再検証のおかげで、特定の URL の次のリクエストでネットワークからの新しいレスポンスが使用されるようにすることができます。
  • デメリット: Service Worker のキャッシュ保存戦略を明確に定義する必要があります。

シナリオ: 短期キャッシュ保存(ネットワークがキャッシュにフォールバック)

  • キャッシュに保存されたリソースが Service Worker のキャッシュで有効な場合(1 日以内): Service Worker はリソースのネットワークにアクセスします。ブラウザは、リソースが HTTP キャッシュに存在する場合は、そこからリソースを返します。ネットワークがダウンしている場合、Service Worker は Service Worker のキャッシュからリソースを返します。
  • サービス ワーカーのキャッシュ内のキャッシュに保存されたリソースの有効期限が切れた場合(1 日以上経過): Service Worker はネットワークにアクセスしてリソースを取得します。ブラウザは、HTTP キャッシュ内のキャッシュ バージョンが期限切れになったため、ネットワーク経由でリソースを取得します。

長所と短所:

  • メリット: ネットワークが不安定な場合やダウンしている場合、Service Worker はキャッシュに保存されたリソースをすぐに返します。
  • デメリット: Service Worker は、HTTP キャッシュをオーバーライドして「ネットワーク優先」リクエストを行うために、追加のキャッシュ無効化を必要とします。

まとめ

キャッシュ保存シナリオの組み合わせは複雑であるため、すべてのケースをカバーする 1 つのルールを設計することはできません。ただし、前のセクションの調査結果に基づいて、キャッシュ戦略を設計する際に考慮すべき提案がいくつかあります。

  • Service Worker のキャッシュ保存ロジックは、HTTP キャッシュの有効期限ロジックと一致する必要はありません。可能であれば、Service Worker でより長い有効期限ロジックを使用して、Service Worker にさらに制御権限を付与します。
  • HTTP キャッシュは依然として重要な役割を果たしていますが、ネットワークが不安定な場合やダウンしている場合は信頼性がありません。
  • 各リソースのキャッシュ保存戦略を見直して、Service Worker のキャッシュ保存戦略が HTTP キャッシュと競合することなく、その価値を提供していることを確認します。

詳細