Webサイトの表示速度を上げる方法のなかで、最も費用対効果が高いのがキャッシュです。適切に設定すれば、2回目以降のアクセスでサーバーへのリクエスト自体が発生せず、体感速度が大きく変わります。一方で設定を誤ると「更新したのに古いファイルが表示され続ける」という厄介な事故が起きます。しかも一度配ってしまったキャッシュは、期限が切れるまで取り消せません。この記事では、HTTPキャッシュを設計する手順を、ヘッダーの理解からCache-Controlの組み立て、ETagによる検証、ファイル種別ごとの戦略まで順番に整理します。
1. キャッシュ関連のヘッダーを把握する
まず、キャッシュに関わるヘッダーの役割を整理します。中心になるのは Cache-Control で、保存期間や再検証の要否を指定します。加えて、コンテンツのバージョンを表す ETag と Last-Modified、そしてブラウザが問い合わせに使う If-None-Match と If-Modified-Since があります。HTTPヘッダーリファレンスで各ヘッダーを引くと、リクエスト側とレスポンス側のどちらで使うものか、どんな値を取るのかを確認できます。古い Expires や Pragma を見かけることもありますが、現在は Cache-Control が優先されるため、新規に設計するなら Cache-Control を中心に考えれば十分です。まずは「保存期間を決めるもの」と「変更されたかを確認するもの」の2系統がある、と捉えると理解しやすくなります。
この手順で使うツール
HTTP Headers Reference
主要 HTTP ヘッダーの用途・構文・使用例をまとめたリファレンス
2. Cache-Control を組み立てる
次に、実際に返す Cache-Control の値を決めます。よく使うディレクティブは、保存してよい時間を秒で指定する max-age、CDNなど共有キャッシュ向けの s-maxage、誰でもキャッシュしてよい public、ブラウザだけに許す private、毎回サーバーに確認させる no-cache、一切保存させない no-store、そして内容が絶対に変わらないことを示す immutable です。紛らわしいのが no-cache と no-store の違いで、no-cache は「保存はするが使う前に必ず確認する」、no-store は「そもそも保存しない」を意味します。個人情報を含むページには no-store を使います。HTTPキャッシュヘッダービルダーで各ディレクティブを選ぶと、生成される値と挙動の説明が同時に確認でき、設定の意図と実際の値のずれを防げます。
この手順で使うツール
HTTP Cache Header Builder
Cache-Control / Vary / ETag ヘッダーをGUIで組み立て・日本語解説付き
3. ETag で「変わっていないこと」を確認させる
max-age が切れた後、ブラウザは再度サーバーに問い合わせます。このとき中身が変わっていなければ、ファイル全体を送り直す必要はありません。それを実現するのが ETag です。サーバーはコンテンツから計算した識別子を ETag として返し、ブラウザは次回 If-None-Match ヘッダーでその値を送ります。サーバー側で一致すれば 304 Not Modified を返し、本文を送らずに済みます。ETag の値にはコンテンツのハッシュがよく使われます。Hash Studio でファイルやテキストの SHA-256 を計算してみると、中身が1文字でも変われば値が全く変わることが確認でき、なぜ変更検知に使えるのかが直感的に分かります。なお、複数台のサーバーで運用する場合、サーバーごとに異なる ETag を返さないよう(ファイルのinode等ではなく内容から生成するよう)注意が必要です。
この手順で使うツール
Hash Studio
MD5 / SHA ハッシュ生成 & 検証
4. ファイルの種類ごとに戦略を分ける
実務では、すべてを同じ設定にせず、ファイルの性質で分けます。定番は「ファイル名にハッシュが付いたビルド成果物(app.a1b2c3.js など)は max-age=31536000, immutable」です。内容が変われば必ずファイル名も変わるため、1年間キャッシュしても事故が起きません。immutable を付けると、リロード時の再確認すら省略されます。一方、HTML は no-cache(毎回確認)にしておくのが安全です。HTMLは参照するJS/CSSのファイル名を含むため、ここが古いままだと新しいファイルにたどり着けないからです。画像やフォントなど更新頻度の低い静的ファイルは、数日〜数か月の max-age が目安になります。APIレスポンスは、更新が即座に反映されるべきものは no-store、変化の少ない一覧などは短い max-age と ETag の組み合わせが向いています。
この手順で使うツール
HTTP Cache Header Builder
Cache-Control / Vary / ETag ヘッダーをGUIで組み立て・日本語解説付き
5. 設定を検証し、事故を防ぐ
最後に、意図した通りに効いているかを確認します。ブラウザの開発者ツールのNetworkタブで、レスポンスヘッダーの Cache-Control と、2回目のアクセスで 304 や「メモリキャッシュから」と表示されるかを見ます。キャッシュを無効化した状態(ハードリロード)と通常の状態を比べると、どのファイルがキャッシュされているかが分かります。設計時に必ず意識しておきたいのは、「長い max-age は取り消せない」という点です。ファイル名にハッシュが付いていない状態で長期キャッシュを設定してしまうと、更新してもユーザーの手元では古いファイルが使われ続け、期限切れまで打つ手がありません。迷ったときは短めの期間から始め、ファイル名にバージョンやハッシュを含める仕組みを整えてから、長期キャッシュへ移行するのが安全です。
まとめ
HTTPキャッシュの設計は「ヘッダーの役割を把握する → Cache-Control を組み立てる → ETagで変更を検知させる → ファイル種別で戦略を分ける → 検証する」という流れで進めると、事故を避けながら効果を出せます。特に「ハッシュ付きファイルは immutable で長期キャッシュ、HTMLは no-cache」という組み合わせは定番として覚えておく価値があります。一度配ったキャッシュは取り消せないという性質を踏まえ、短めから始めて確実に運用するのが安全です。