Help us understand the problem. What is going on with this article?

静的リソース(HTML,JS,CSS,画像)のブラウザキャッシュを制御

More than 5 years have passed since last update.

前回のエントリ(ブラウザのキャッシュコントロールを正しく理解する)でブラウザ側のキャッシュ制御について説明しました。
ただ動的スクリプトなら、次の例のようにHTTPレスポンスヘッダを操作すればいいのですが、

PHPでのHTTPレスポンスヘッダ出力例
<?php
header('Content-Type: text/plain; charset=UTF-8');
header('Cache-Control: max-age=0');
echo "Hello World!";
?>

スクリプトを介さない静的リソース(HTMLファイル、JSファイル、CSSファイル、画像ファイルなど)はどうやってHTTPレスポンスを操作すればいいかというと、もしApacheを利用している場合は mod_header と mod_rewrite を利用して次のように簡単に出来ます!

設定例

想定ケースとして、次のようにブラウザ側のキャッシュを制御したいと仮定します。
(表の下にいくほど、キャッシュの強度が高い=サーバ側へのアクセス回数や通信量を抑えられる)

対象 期待する挙動
PHPスクリプト ブラウザにキャッシュされず毎回アクセスして欲しい。動的コンテンツなのでサーバから304レスポンスを返すこともない。
HTMLファイル コンテンツに文言ミスがあった場合に、修正を即座に反映したい。ただサイズが大きいので、普段に変更がない場合はコンテンツ内容をレスポンスしたくない(304レスポンス)
CSSファイル、JSファイル 何かアプリケーションに不具合があった場合に修正を反映したいが、最悪10分間は許容できる。サイズが大きいので普段に変更がない場合はコンテンツ内容をレスポンスしたくない(304レスポンス)
画像ファイル 運用でめったに更新しない。修正した場合も反映まで1日は許容できる。サイズが大きいので普段に変更がない場合はコンテンツ内容をレスポンスしたくない(304レスポンス)

この要件を満たすには、次のように .htaccess へ記載します。

.htaccess
RewriteEngine on

RewriteRule \.php$ - [L,E=X_CACHE_PATTERN1:]
RewriteRule \.html$ - [L,E=X_CACHE_PATTERN2:]
RewriteRule \.(css|js)$ - [L,E=X_CACHE_PATTERN3:]
RewriteRule \.(gif|jpe?g|png)$ - [L,E=X_CACHE_PATTERN4:]

# For dynamic contents
Header set Cache-Control "no-cache" env=X_CACHE_PATTERN1
Header unset Expires env=X_CACHE_PATTERN1
Header unset Last-Modified env=X_CACHE_PATTERN1
Header unset Etag env=X_CACHE_PATTERN1

# For HTML files
Header set Cache-Control "max-age=0" env=X_CACHE_PATTERN2
Header set Expires "Mon, 26 Jul 1997 05:00:00 GMT" env=X_CACHE_PATTERN2

# For CSS,JavaScript files
Header set Cache-Control "max-age=600" env=X_CACHE_PATTERN3

# For Image files
Header set Cache-Control "max-age=86400" env=X_CACHE_PATTERN4

ファイルの拡張子を元に、キャッシュのパターンを4通り設定しています。
(テンポラリ的にApache環境変数を利用。)

《拡張子が .php の場合》
HTTPレスポンスヘッダ Cache-Control: no-cache をセットし、Expires Last-Modified Etag は念のため削除しています(なんとなく気持ち悪いので)。


《拡張子が .html の場合》
Cache-ControlExpires で、即に期限切れにしています。Last-Modified Etag はApacheで自動的に付与されます(特殊な設定変更をしていなければ)。


《拡張子が .css または .js の場合》
Cache-Control: max-age=600 で600秒(10分間)のキャッシュを指定しています。こちらもLast-Modified Etag はApacheで自動的に付与されます。
本当はExpiresも設定したいところですが .htaccess で時間計算や文字列生成ができないので^^; ただ大抵のブラウザは、Cache-Control だけで十分かと思います。


《拡張子が画像系ファイルの場合》
CSSやJSの時よりキャッシュ期間を長く(max-age=86400:1日)しています。

おわりに

静的リソースのブラウザキャッシュを制御することによって、ユーザのブラウザ描写待ち時間も減るとともに、サーバの負荷やネットワーク通信量を抑えられます。
とくに大きい画像がある場合はキャッシュは効果が高いので、適切に設定しましょう!

hkusu
Software Engineer @ Yumemi, Inc JavaScript / Android / Kotlin / AWS etc..
http://hkusu.github.io
yumemi
みんなが知ってるあのサービス、実はゆめみが作ってます。スマホアプリ/Webサービスの企画・UX/UI設計、開発運用。Swift, Kotlin, PHP, Vue.js, React.js, Node.js, AWS等エンジニア・クリエイターの会社です。Twitterで情報配信中https://twitter.com/yumemiinc
http://www.yumemi.co.jp
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away