mybook

第3章 — HTTP キャッシュ: Web の心臓部

「HTTP ヘッダーだけで世界が変わる」

ケンジがマナミに言った。

「アプリケーションに1行もキャッシュコードを書かなくても、HTTP ヘッダーを正しく設定するだけでレスポンスが劇的に速くなる。HTTP キャッシュは Web パフォーマンスの心臓部だ」

Cache-Control ヘッダー

最も重要なキャッシュ制御ヘッダー。レスポンスのキャッシュ方法を指示する。

Cache-Control: public, max-age=31536000, immutable

主要なディレクティブ

ディレクティブ意味
publicCDN・プロキシでキャッシュ可
privateブラウザのみキャッシュ可(ユーザー固有データ)
no-cacheキャッシュ可だが毎回検証が必要
no-store一切キャッシュ禁止
max-age=NN秒間有効
s-maxage=NCDN/プロキシで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

項目ETagLast-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
HTMLno-cache + ETag常に最新版を検証。304で帯域節約
API(公開)public, s-maxage=60, stale-while-revalidate=300CDN キャッシュ + バックグラウンド更新
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 キャッシュを学ぶ。