第3章 — HTTP キャッシュ: Web の心臓部
「HTTP ヘッダーだけで世界が変わる」
ケンジがマナミに言った。
「アプリケーションに1行もキャッシュコードを書かなくても、HTTP ヘッダーを正しく設定するだけでレスポンスが劇的に速くなる。HTTP キャッシュは Web パフォーマンスの心臓部だ」
Cache-Control ヘッダー
最も重要なキャッシュ制御ヘッダー。レスポンスのキャッシュ方法を指示する。
Cache-Control: public, max-age=31536000, immutable
主要なディレクティブ
| ディレクティブ | 意味 |
|---|---|
public | CDN・プロキシでキャッシュ可 |
private | ブラウザのみキャッシュ可(ユーザー固有データ) |
no-cache | キャッシュ可だが毎回検証が必要 |
no-store | 一切キャッシュ禁止 |
max-age=N | N秒間有効 |
s-maxage=N | CDN/プロキシでN秒間有効(max-ageより優先) |
immutable | 有効期限内は再検証も不要 |
stale-while-revalidate=N | 古いキャッシュを返しつつ裏で更新 |
WARNING
no-cache は「キャッシュしない」ではない! 「キャッシュするが、使う前に必ずサーバーに確認する」という意味。キャッシュを完全に禁止するのは no-store。
条件付きリクエスト: ETag と Last-Modified
ETag(Entity Tag)
レスポンスの「指紋」。コンテンツが変わればETagも変わる。
Loading diagram...
Last-Modified
最終更新日時ベースの検証。
# レスポンス
Last-Modified: Wed, 21 Oct 2025 07:28:00 GMT
# 次回リクエスト
If-Modified-Since: Wed, 21 Oct 2025 07:28:00 GMT
ETag vs Last-Modified
| 項目 | ETag | Last-Modified |
|---|---|---|
| 精度 | コンテンツレベル | 秒単位 |
| 計算コスト | ハッシュ計算が必要 | ファイルシステムから取得 |
| 使いどころ | 動的コンテンツ | 静的ファイル |
Vary ヘッダー
同じURLでもリクエストヘッダーの違いで異なるレスポンスを返す場合に使う。
Vary: Accept-Encoding, Accept-Language
これにより、gzip版と非圧縮版、日本語版と英語版を別々にキャッシュできる。
WARNING
Vary: * はキャッシュを完全に無効化する。Vary: Cookie も実質的にキャッシュが効かなくなる(Cookie はユーザーごとに異なるため)。
stale-while-revalidate
古いキャッシュを即座に返しつつ、裏で新しいデータを取得する戦略。ユーザー体験と鮮度を両立する。
Cache-Control: max-age=60, stale-while-revalidate=3600
Loading diagram...
実践: リソース種別ごとの戦略
Loading diagram...
| リソース種別 | 推奨設定 | 理由 |
|---|---|---|
| JS/CSS(ハッシュ付き) | public, max-age=31536000, immutable | ファイル名にハッシュ含むので変更時は別URL |
| HTML | no-cache + ETag | 常に最新版を検証。304で帯域節約 |
| API(公開) | public, s-maxage=60, stale-while-revalidate=300 | CDN キャッシュ + バックグラウンド更新 |
| API(個人) | private, no-cache | ユーザー固有データは CDN に載せない |
| 認証トークン | no-store | 一切キャッシュ禁止 |
マナミの実装
マナミは FreshMarket に以下の HTTP キャッシュ戦略を導入した:
# Nginx 設定
# 静的アセット(1年キャッシュ)
location /assets/ {
add_header Cache-Control "public, max-age=31536000, immutable";
}
# 商品一覧 API(CDN 60秒 + SWR 5分)
location /api/products {
add_header Cache-Control "public, s-maxage=60, stale-while-revalidate=300";
add_header Vary "Accept-Encoding";
}
# ユーザー固有データ
location /api/user/ {
add_header Cache-Control "private, no-cache";
}
# 決済関連
location /api/checkout/ {
add_header Cache-Control "no-store";
}Loading chart...
HTTP キャッシュ設定だけで、平均レスポンスタイムが 70% 改善した。
次の章では、HTTP キャッシュをさらに加速させる CDN キャッシュを学ぶ。