HTTP キャッシュ
Cache-Control, ETag, Last-Modified を使った HTTP レベルのキャッシュ制御
HTTPパフォーマンス
HTTP キャッシュとは
HTTP キャッシュは、Cache-Control、ETag、Last-Modified ヘッダーを使って、ブラウザや CDN にレスポンスをキャッシュさせる仕組みである。同じリソースへの再リクエストを削減し、ページの表示速度を向上させ、サーバーの負荷を軽減する。
Cache-Control ヘッダー
Cache-Control: public, max-age=31536000, immutable
| ディレクティブ | 意味 |
|---|---|
public |
CDN やプロキシでもキャッシュ可能 |
private |
ブラウザのみキャッシュ可能 (CDN 不可) |
max-age=N |
N 秒間キャッシュを有効とする |
no-cache |
キャッシュするが、使用前にサーバーに検証する |
no-store |
一切キャッシュしない |
immutable |
max-age 内は再検証しない |
stale-while-revalidate=N |
期限切れ後 N 秒間は古いキャッシュを返しつつ裏で更新 |
コンテンツ種別ごとの設定
| コンテンツ | Cache-Control | 理由 |
|---|---|---|
| JS/CSS (ハッシュ付き) | public, max-age=31536000, immutable |
ファイル名にハッシュを含むため、内容が変わればURLが変わる |
| 画像 | public, max-age=2592000 |
30日キャッシュ |
| HTML | public, max-age=0, must-revalidate |
常にサーバーに検証 |
| API レスポンス | no-store |
キャッシュしない |
| ユーザー固有データ | private, no-store |
CDN にキャッシュさせない |
ETag による条件付きリクエスト
1回目のリクエスト:
GET /api/users/123
→ 200 OK
→ ETag: "abc123"
→ Cache-Control: no-cache
2回目のリクエスト:
GET /api/users/123
If-None-Match: "abc123"
→ 304 Not Modified (ボディなし、帯域節約)
or
→ 200 OK + 新しい ETag (データが変更された場合)
ETag はレスポンスのハッシュ値で、データが変更されていなければ 304 を返す。レスポンスボディの転送を省略できる。
CloudFront でのキャッシュ制御
CloudFront はオリジンの Cache-Control ヘッダーに従ってキャッシュする。キャッシュポリシーでオーバーライドも可能。
stale-while-revalidate
Cache-Control: public, max-age=300, stale-while-revalidate=60
300 秒間はキャッシュを返す。300〜360 秒の間は古いキャッシュを即座に返しつつ、バックグラウンドでオリジンから最新データを取得する。ユーザーは常に即座にレスポンスを受け取れる。
よくある失敗
HTML に長い max-age を設定
HTML に max-age=31536000 を設定すると、デプロイしても古い HTML がキャッシュから返り続ける。HTML は max-age=0 にし、JS/CSS はファイル名ハッシュ + 長い max-age にする。
理論と実装の両面から学ぶなら関連書籍が参考になる。