Back

すべてのWeb開発者が知っておくべきキャッシングの基礎

すべてのWeb開発者が知っておくべきキャッシングの基礎

ユーザーがボタンをクリックしたのに、3秒間何も起こらない。データベースクエリは完了し、サーバーは応答したのに、昨日読み込んだのと同じデータが再びインターネット全体を経由して送信されなければならなかった。これがキャッシングが解決する問題です。

HTTPキャッシングの基礎を理解することは、フロントエンド開発者にとって任意ではありません。これは、キビキビと動作するアプリケーションと壊れているように感じるアプリケーションの違いです。このガイドでは、ブラウザキャッシュとCDNキャッシュの違い、Cache-Controlヘッダー、そしてETagやLast-Modifiedのような検証メカニズムについて知っておくべきことをカバーします。

重要なポイント

  • 予測不可能なブラウザのヒューリスティックを避けるため、すべてのレスポンスに明示的なCache-Controlヘッダーを設定する。
  • 静的アセットには、キャッシュバスティング(コンテンツハッシュ化されたファイル名)と組み合わせて長いmax-age値を使用する。
  • 常に新鮮である必要があるコンテンツには、ETagまたはLast-Modifiedと共にno-cacheを使用する。
  • パーソナライズされたコンテンツや認証が必要なコンテンツは、共有キャッシュを通じたデータ漏洩を防ぐため、常にprivateとしてマークする。

キャッシングとは何か、そしてなぜ重要なのか

キャッシングは、データのコピーを必要な場所により近い場所に保存します。ブラウザが画像をリクエストすると、その画像をローカルに保存できます。次のリクエストでは、ネットワークを完全にスキップします。

パフォーマンスの向上は劇的です。例えば、データベースクエリには数十ミリ秒かかる可能性がありますが、ブラウザキャッシュからの読み取りは通常ほぼ瞬時であり、ネットワークのラウンドトリップを完全に回避します。

キャッシングは3つの主要な利点を提供します:

  • レイテンシの削減: データがより短い距離を移動する。
  • サーバー負荷の軽減: オリジンサーバーに到達するリクエストが減少する。
  • より良いユーザー体験: 再訪問時にページがより速く読み込まれる。

キャッシュレイヤーの理解

リクエストは、サーバーに到達する前に複数のキャッシュを通過します。各レイヤーは異なる目的を果たします。

ブラウザキャッシュ(プライベートキャッシュ)

ブラウザキャッシュはユーザーのデバイス上に存在します。そのユーザーのみが見るべきレスポンスを保存します。レスポンスをprivateとしてマークすると、ここに留まり、他のユーザーと共有されることはありません。

これは、パーソナライズされたコンテンツが属する場所です — ユーザープロフィール、認証されたAPIレスポンス、特定のセッションに紐付けられたあらゆるものです。

CDNキャッシュ(共有キャッシュ)

CDNキャッシュは、ユーザーとオリジンサーバーの間に位置し、地理的な場所に分散されています。東京のユーザーがJavaScriptバンドルをリクエストすると、CDNはオリジンデータセンターではなく、近くのエッジサーバーからそれを提供します。

CDNは静的アセットのキャッシングに優れています:画像、CSS、JavaScript、フォントなど。慎重な設定が必要ですが、公開APIレスポンスもキャッシュできます。

サーバーサイドキャッシング

HTTPキャッシングを超えて、サーバーはRedisやMemcachedのようなツールを使用して独自のキャッシュを維持することがよくあります。フロントエンド開発者として、これらを直接設定することはありませんが、それらが存在することを理解することで、なぜ一部のAPIレスポンスが他よりも速いのかを理解するのに役立ちます。

Cache-Controlヘッダー: コアディレクティブ

Cache-Controlヘッダーは、キャッシュにレスポンスの処理方法を指示します。最も頻繁に使用するディレクティブは次のとおりです:

ディレクティブ意味
max-age=36003600秒(1時間)キャッシュする
no-cache保存するが、使用前に再検証する
no-storeこのレスポンスをどこにも保存しない
privateブラウザキャッシュのみがこれを保存できる
publicすべてのキャッシュがこれを保存できる

よくある間違い:no-cacheは「キャッシュしない」という意味ではありません。「キャッシュされたコピーを使用する前に常にサーバーで確認する」という意味です。キャッシングを本当に一切行いたくない場合はno-storeを使用してください。

ハッシュ化されたファイル名を持つ静的アセットには、積極的なキャッシングを使用します:

Cache-Control: public, max-age=31536000

頻繁に変更されるHTMLページ(特に機密性の高いコンテンツや非常に動的なコンテンツ)には:

Cache-Control: no-cache, private

ETagとLast-Modified: 検証メカニズム

キャッシュされたコンテンツが期限切れになったとき、ブラウザは常にすべてを再ダウンロードする必要はありません。検証ヘッダーは効率的な再検証を可能にします。

Last-Modifiedにはタイムスタンプが含まれます。後続のリクエストで、ブラウザはそのタイムスタンプと共にIf-Modified-Sinceヘッダーを送信します。何も変更されていない場合、サーバーは304 Not Modifiedを返します — ボディなし、最小限の帯域幅です。

ETagには一意の識別子(多くの場合コンテンツハッシュ)が含まれます。後続のリクエストで、ブラウザはその識別子と共にIf-None-Matchヘッダーを送信します。同じ結果:コンテンツが変更されていない場合は304です。

ETagはタイムスタンプよりも正確です。なぜなら、実際のコンテンツの変更を検出するからです。ファイルはコンテンツを変更せずに再保存される可能性があり、タイムスタンプは更新されますがETagは更新されません。

静的アセットのキャッシュバスティング

静的アセットをできるだけ長くキャッシュしたいと同時に、デプロイ時にユーザーが更新を取得する必要があります。キャッシュバスティングは、コンテンツが変更されたときにURLを変更することでこれを解決します。

最新のビルドツールは、ファイル名にコンテンツハッシュを追加します:

bundle.a1b2c3d4.js
styles.e5f6g7h8.css

新しいコードをデプロイすると、ハッシュが変わり、URLが変わり、ブラウザは新しいバージョンを取得します。古いキャッシュされたファイルは自然に期限切れになるだけです。

避けるべき一般的な落とし穴

認証されたコンテンツを公開でキャッシュする: ユーザー固有のデータには常にprivateを使用してください。共有キャッシュを通じてあるユーザーのデータを別のユーザーに漏洩させることは、深刻なセキュリティ問題です。

APIレスポンスの過度なキャッシング: 動的データには短いTTLまたはno-cacheが必要です。チェックアウト時の古い価格は実際の問題を引き起こします。

ヘッダーの設定を忘れる: 明示的なCache-Controlヘッダーがない場合、ブラウザはレスポンスメタデータに基づいてヒューリスティックキャッシングを適用する可能性があり、意図しない動作につながる可能性があります。

結論

キャッシングは、一度設定して忘れるものではありません。すべてのレスポンスに明示的なCache-Controlヘッダーを設定してください。静的アセットには、コンテンツハッシュ化されたファイル名と組み合わせて長いmax-age値を使用します。常に新鮮である必要があるコンテンツには、ETagまたはLast-Modifiedと共にno-cacheを使用し、パーソナライズされたコンテンツは常にprivateとしてマークします。DevToolsでヘッダーを確認し、CDNの動作を検証し、ユーザーが実際に体験することをテストしてください。

よくある質問

no-cacheは、ブラウザがレスポンスを保存できるが、使用する前にサーバーで再検証する必要があることを伝えます。no-storeは、ブラウザにレスポンスを全く保存しないように伝えます。銀行の詳細のような機密データにはno-storeを使用し、頻繁に変更されるが条件付き再検証の恩恵を受けるコンテンツにはno-cacheを使用してください。

ブラウザのDevToolsを開き、Networkタブに移動し、任意のリクエストを選択します。Response Headersセクションに、Cache-Control、ETag、Last-Modified値が表示されます。sizeカラムも確認してください。disk cacheまたはmemory cacheと表示されている場合、レスポンスはネットワークではなくブラウザキャッシュから提供されました。

データによります。製品カテゴリのような公開されたほとんど変更されないデータは、短いmax-age値を使用できます。ユーザー固有または頻繁に変更されるデータは、検証ヘッダー付きのno-cacheまたはno-storeを使用すべきです。CDNがあるユーザーのデータを別のユーザーに提供するのを防ぐため、認証されたレスポンスは常にprivateとしてマークしてください。

コンテンツハッシュにより、静的アセットに非常に長いキャッシュライフタイムを設定しながら、更新を即座に配信できます。ファイルのコンテンツが変更されると、ハッシュが変更され、既存のキャッシュをバイパスする新しいURLが生成されます。この技術はキャッシュバスティングと呼ばれ、Webpack、Vite、Rollupのようなツールで使用される標準的なアプローチです。

Gain control over your UX

See how users are using your site as if you were sitting next to them, learn and iterate faster with OpenReplay. — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data. Check our GitHub repo and join the thousands of developers in our community.

OpenReplay