Service Worker のキャッシュ レイヤと HTTP キャッシュ レイヤで一貫した有効期限ロジックまたは異なる有効期限ロジックを使用するメリットとデメリット。
Service Worker と PWA が最新のウェブ アプリケーションの標準になりつつある一方で、リソース キャッシュはこれまで以上に複雑になっています。この記事では、以下を含むブラウザ キャッシュの全体像について説明します。
- Service Worker のキャッシュ保存と HTTP のキャッシュ保存のユースケースと相違点。
- さまざまな Service Worker のキャッシュ保存の有効期限戦略と、通常の HTTP キャッシュ保存戦略のメリットとデメリットの比較。
キャッシュ フローの概要
大まかに言うと、ブラウザはリソースをリクエストするときに以下のキャッシュ順序に従います。
- Service Worker のキャッシュ: Service Worker は、リソースがキャッシュ内にあるかどうかを確認し、プログラムされたキャッシュ戦略に基づいてリソース自体を返すかどうかを決定します。これは自動的には行われないことに注意してください。Service Worker にフェッチ イベント ハンドラを作成し、ネットワーク リクエストをインターセプトして、リクエストがネットワークではなく Service Worker のキャッシュから提供されるようにする必要があります。
- HTTP キャッシュ(ブラウザ キャッシュとも呼ばれます): リソースが HTTP キャッシュで見つかり、まだ期限切れになっていない場合、ブラウザは HTTP キャッシュのリソースを自動的に使用します。
- サーバー側: Service Worker キャッシュまたは HTTP キャッシュに何も見つからない場合、ブラウザはネットワークにアクセスしてリソースをリクエストします。リソースが CDN のキャッシュに保存されていない場合、リクエストは送信元サーバーにまで戻る必要があります。
キャッシュ レイヤ
Service Worker のキャッシュ保存
Service Worker はネットワーク タイプの HTTP リクエストをインターセプトし、キャッシュ戦略を使用して、ブラウザに返すリソースを決定します。Service Worker のキャッシュと HTTP キャッシュは同じ汎用性を発揮しますが、Service Worker のキャッシュは、キャッシュに保存される内容やキャッシュの実行方法をきめ細かく制御するなど、より多くのキャッシュ機能を提供します。
Service Worker のキャッシュの制御
Service Worker は、イベント リスナー(通常は fetch
イベント)を使用して 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 のキャッシュ保存のその他のメリット
Service Worker のキャッシュ保存では、キャッシュ ロジックを細かく制御できるだけでなく、次の機能も利用できます。
- 送信元のメモリとストレージ容量の増加: ブラウザは、HTTP キャッシュ リソースを送信元ごとに割り当てます。つまり、複数のサブドメインがある場合、それらはすべて同じ HTTP キャッシュを共有します。送信元/ドメインのコンテンツが HTTP キャッシュに長期間保持される保証はありません。たとえば、ユーザーがブラウザの設定 UI から手動でクリーンアップしたり、ページでハードリロードをトリガーしたりすることで、キャッシュを削除できます。Service Worker のキャッシュを使用すると、キャッシュに保存されたコンテンツがキャッシュに保存されたままになる可能性が高くなります。詳細については、永続ストレージをご覧ください。
- 不安定なネットワークやオフライン エクスペリエンスでの高い柔軟性: HTTP キャッシュでは、リソースをキャッシュに保存するかどうかの二者択一しか選べません。Service Worker のキャッシュを使用すると、「stale-while-revalidate」戦略により、わずかな「中断」をはるかに簡単に軽減できます。また、「Cache only」戦略で完全なオフライン エクスペリエンスを提供できます。たとえば、UI をカスタマイズして Service Worker のキャッシュから取得し、一部を「キャッチ ハンドラの設定」戦略で除外できます。
HTTP キャッシュ
ブラウザは、ウェブページと関連リソースを初めて読み込むときに、これらのリソースを HTTP キャッシュに保存します。HTTP キャッシュは通常、エンドユーザーによって明示的に無効にされていない限り、ブラウザによって自動的に有効になります。
HTTP キャッシュを使用する場合、リソースをキャッシュに保存するタイミングと保存期間はサーバーに依存します。
HTTP レスポンス ヘッダーを使用して HTTP キャッシュの有効期限を制御する
サーバーがリソースに関するブラウザ リクエストに応答する際、サーバーは HTTP レスポンス ヘッダーを使用して、リソースをキャッシュに保存する期間をブラウザに伝えます。詳しくは、レスポンス ヘッダー: ウェブサーバーの構成をご覧ください。
HTTP キャッシュの戦略とユースケース
HTTP キャッシュは時間ベース(TTL)のリソース有効期限ロジックのみを処理するため、HTTP キャッシュは Service Worker のキャッシュよりもはるかにシンプルです。HTTP キャッシュ戦略の詳細については、使用すべきレスポンス ヘッダー値の選択と概要をご覧ください。
キャッシュの有効期限ロジックの設計
このセクションでは、Service Worker のキャッシュ レイヤと HTTP キャッシュ レイヤで一貫した有効期限ロジックを使用する場合の長所と短所について説明します。また、これらのレイヤ間で個別の有効期限ロジックを使用することのメリットとデメリットについても説明します。
以下の Glitch は、さまざまなシナリオで Service Worker のキャッシュ保存と HTTP キャッシュがどのように機能するかを示しています。
すべてのキャッシュ レイヤで一貫した有効期限ロジック
メリットとデメリットを示すために、長期、中期、短期の 3 つのシナリオを見ていきます。
シナリオ | 長期キャッシュ | 中期キャッシュ保存 | 短期キャッシュ |
---|---|---|---|
Service Worker のキャッシュ戦略 | キャッシュ、ネットワークにフォールバック | 最新でない再検証 | ネットワーク キャッシュへのフォールバック |
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 のキャッシュ戦略 | キャッシュ、ネットワークにフォールバック | 最新でない再検証 | ネットワーク キャッシュへのフォールバック |
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 は、キャッシュに保存されたリソースを直ちに返します。
- キャッシュに保存されたリソースが Service Worker のキャッシュで期限切れになった場合(30 日超): Service Worker はリソースを求めてネットワークに移動します。ブラウザの HTTP キャッシュにリソースのコピーがないため、ブラウザはサーバー側で処理されます。
長所と短所:
- メリット: Service Worker はキャッシュに保存されたリソースをすぐに返すため、すぐにレスポンスが返されます。
- メリット: 再検証が「バックグラウンドで」行われるので、Service Worker は特定の URL に対する次のリクエストで、ネットワークからの最新のレスポンスを使用できます。
- デメリット: 明確に定義された Service Worker のキャッシュ戦略が必要です。
シナリオ: 短期キャッシュ(キャッシュへのネットワーク フォールバック)
- キャッシュに保存されたリソースが Service Worker のキャッシュで有効な場合(1 日以内): Service Worker はリソースを求めてネットワークに移動します。リソースが存在する場合、ブラウザは HTTP キャッシュからそのリソースを返します。ネットワークがダウンした場合、Service Worker は 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 キャッシュと競合することなく価値を提供できるようにします。