CloudFront+S3構成でブラウザキャッシュが効かない問題を解決!

CloudFront+S3構成でブラウザキャッシュが効かない問題を解決!

CloudFront + S3 で max-age: 14400 をレスポンスヘッダーに入れても毎回 CloudFront に対してリクエストを投げてしまう問題を解決したので手法をまとめておく。

先日、自身が運営するWebサイトのパフォーマンス改善に取り組む中で、CDNとしてAWS CloudfrontとオリジンサーバーとしてS3を採用し、高速化を目指していました。しかし、設定を施しても期待通りに動作せず、ブラウザキャッシュが有効にならないため、Cloudfrontへのリクエストが頻発するという問題に直面してしまいました。

本記事では、私が経験した「CDN設定の落とし穴」を赤裸々に公開し、試行錯誤の末にたどり着いた解決策と、その背後にある技術的メカニズムについて詳細に解説します。

エッジキャッシュとブラウザキャッシュについて

私の運営するWebサイトは、ユーザーが投稿した大量の画像や動画コンテンツを扱うため、ページ容量が大きくなりがちで、表示速度の低下が課題となっていました。そこで、コンテンツ配信を高速化し、サーバー負荷を軽減するために、AWS CloudfrontとS3の組み合わせを採用することにしました。

Cloudfrontは、世界中に分散配置されたエッジロケーションを通じて、コンテンツをユーザーに近いサーバーから配信することで、高速かつ低遅延なコンテンツ配信を実現するサービスです。さらに、キャッシュ機能を利用することで、オリジンサーバーであるS3へのリクエストを削減し、Webサーバーの負荷を大幅に軽減することができます。

一方、ブラウザキャッシュは、ユーザーのブラウザがWebページのリソース(画像、CSS、JavaScriptファイルなど)をローカルに保存し、次回アクセス時にサーバーへのリクエストを省略することで、ページの読み込みを高速化する仕組みです。

Cloudfrontとブラウザキャッシュを組み合わせることで、S3への負荷を最小限に抑えつつ、ユーザーに対して高速なコンテンツ配信を実現できると期待していました。

なぜ効かない?ブラウザキャッシュ: 試行錯誤と原因究明

CloudfrontとS3の構成を構築し、期待を込めてWebサイトにアクセスしてみたものの、パフォーマンスは思ったように改善しませんでした。ブラウザの開発者ツールで確認すると、コンテンツがキャッシュされず、毎回Cloudfrontへのリクエストが発生していることが判明しました。

そこで、私はブラウザキャッシュの動作原理を改めて確認し、Cloudfrontの設定を見直すことにしました。

ブラウザキャッシュは、主にHTTPヘッダーのCache-Controlディレクティブによって制御されます。max-ageディレクティブは、リソースをキャッシュに保持する最大時間を秒単位で指定します。

私はCloudfrontのビヘイビア設定でCache-Control: max-age=14400を指定し、コンテンツを4時間キャッシュするように設定していました。しかし、ブラウザはこれを無視して、毎回Cloudfrontにリクエストを送信しているように見えました。

原因究明のために、Cloudfrontから返却されるHTTPレスポンスヘッダーを詳しく調査した結果、AgeDateヘッダーがCloudfront側で付与されていることに気づきました。

  • Ageヘッダー: オブジェクトがキャッシュに格納されてからの経過時間を秒単位で表します。
  • Dateヘッダー: オリジンサーバーがリクエストを処理した日時を表します。

ブラウザは、Cache-Control: max-ageディレクティブと共に、これらのヘッダー情報を参照して、キャッシュの有効性を判断します。ポイントは、Cache-Control: max-age の値は、Age, Date の値からの経過時間として考慮される という点です。

私のケースでは、CloudfrontがAgeDateヘッダーを付与していたため、ブラウザはキャッシュの有効期限を「CDNにキャッシュされてからの時間 + max-age」と解釈していました。つまり、Ageの値が大きくなると、max-ageで指定した時間よりも早くキャッシュ期限切れと判断されてしまう状況でした。

解決策発見!レスポンスヘッダーのカスタマイズでブラウザキャッシュを制御

問題の原因がAgeDateヘッダーにあると特定できたため、Cloudfrontの動作をカスタマイズし、これらのヘッダーをレスポンスから排除することで、ブラウザキャッシュを有効化することにしました。

  1. Cloudfrontディストリビューションの設定変更

    • Cloudfrontコンソールにアクセスし、対象のディストリビューションを選択します。
    • 「Behaviors」タブを選択し、編集するビヘイビアを選択します。
    • 「Cache Settings」セクションで、「Customize」を選択します。
    • 「Cache Policy」を作成または選択します。
  2. レスポンスヘッダーポリシーの設定

    • 新規にレスポンスヘッダーポリシーを作成するか、既存のポリシーを編集します。
    • 「カスタムヘッダー」セクションで、「追加」をクリックし、以下を設定します。
      • 名前: cache-control
      • 値: max-age=14400
    • 「ヘッダーを削除」セクションで、「追加」をクリックし、AgeDate をそれぞれ追加します。

レスポンスヘッダーポリシーの設定

これらの設定により、CloudfrontはS3から取得したレスポンスヘッダーからAgeDateヘッダーを削除し、Cache-Control: max-age=14400 を追加してクライアントに返却するようになります。

キャッシュ有効化!パフォーマンス改善と今後の展望

上記の対応を実施した結果、ブラウザキャッシュが正常に動作するようになり、Webサイトのパフォーマンスは劇的に改善しました。ページの読み込み時間が大幅に短縮され、ユーザーエクスペリエンスが向上しただけでなく、Cloudfrontへのリクエスト数も減少したため、コスト削減にも繋がりました。

今回の経験を通して、CDNとブラウザキャッシュの連携は、Webパフォーマンス最適化において非常に重要であることを改めて実感しました。また、HTTPヘッダーの理解を深め、Cloudfrontの動作を細かく制御することの重要性を学びました。

今後は、キャッシュ戦略をさらに進化させ、ユーザーにより快適なWeb体験を提供できるよう、以下の取り組みを進めていきたいと考えています。

  • キャッシュ時間の最適化: コンテンツの更新頻度に応じて、max-ageの値を動的に変更することを検討します。
  • キャッシュバージョニング: クエリパラメータやHTTPヘッダーを利用したキャッシュバージョニングの導入を検討します。
  • HTTP/2 Server Push: CloudfrontのHTTP/2 Server Push機能を活用し、必要なリソースを事前にプッシュすることで、さらなる高速化を目指します。

Webパフォーマンス最適化は、終わりなき旅です。今後も最新技術やベストプラクティスを学び続け、ユーザーに最高のWeb体験を提供できるよう、Webサイトの改善に継続的に取り組んでいきます。