HTTP Cache-Control: immutable と stale-while-revalidate の違い
HTTP Performance Frontend Backend
結論
完全不変なアセットには immutable、裏で最新化したいデータには stale-while-revalidate を使います。
# MDN / RFC 8246 仕様:ハッシュ付きJS/CSS用キャッシュヘッダー
Cache-Control: public, max-age=31536000, immutable
# MDN / RFC 5861 仕様:SWR型キャッシュヘッダー
Cache-Control: public, max-age=60, stale-while-revalidate=3600
MDN公式仕様:2つの拡張ディレクティブの挙動比較
| 評価軸 | immutable (RFC 8246) | stale-while-revalidate (RFC 5861) |
|---|---|---|
| 主な用途 | ハッシュ付きJS/CSS(例: main.a8f9b.js) | Topページ、動的コンテンツ、SWR通信 |
| リロード(F5)時の挙動 | サーバーへの304確認リクエストを完全切断 | 古いキャッシュを即時返しつつバックグラウンド取得 |
| ユーザーへのデータ反映 | キャッシュ期限内は常に同一ファイルを返却 | 1回目は古いデータ、2回目描画時に最新が反映 |
実際に起こる事故:index.html に immutable を付与して詰むトラブル
Web開発現場で発生する最も深刻なトラブルは、ファイル名が変わらない HTML ファイル(index.html)に immutable を指定してしまう事故です。
immutable が付与されると、ブラウザはユーザーがF5更新ボタンを押そうと、max-age 期間中はサーバーにリクエスト(If-None-Match)を一切送信しなくなります。その結果、新バージョンをデプロイしても index.html 内の参照ファイルパスが書き換わらず、ユーザーはブラウザのキャッシュを完全手動削除しない限り永遠に新画面が表示されない障害が発生します。
適切なヘッダー割り当てルール
index.htmlなどエントリーポイント
Cache-Control: no-cache(毎回サーバーに304確認)またはmax-age=0, must-revalidatebundle-[hash].js,style-[hash].css, 画像アセット
Cache-Control: public, max-age=31536000, immutable- API レスポンス・更新頻度の高いコンテンツ
Cache-Control: public, max-age=10, stale-while-revalidate=60