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

ブラウザのキャッシュコントロールを正しく理解する

More than 1 year has passed since last update.

①ブラウザに一切、キャッシュさせたくない場合

サーバからクライアントへのHTTP応答ヘッダ
Cache-Control "no-cache"

アクセス毎に内容が変わったり、サーバにアクセスしてもらわないと困るようなコンコンテンツの場合です。
スクリプト言語等で生成する動的コンテンツは、このようにした方が安全です。

例えば対象コンテンツが画像である場合、ブラウザで同じ画像のURLが含まれたHTMLを開いた場合は、

  • もちろんローカルにキャッシュがないので、サーバへ問い合わせを行う
  • 条件つきリクエスト(If-Modified-Since、If-None-Match)もサーバへ送ってこない

②ブラウザにキャッシュさせるけど、変更ないか都度確認するようにしたい

サーバからクライアントへのHTTP応答ヘッダ
Cache-Control "max-age=0"
Expires "Mon, 26 Jul 1997 05:00:00 GMT"

ブラウザ毎に片方しかサポートしていない場合があるので、両方のヘッダを指定しておいた方がいいです。
最初から既に期限切れ、という意味です。

ブラウザで同じ画像のURLが含まれたHTMLを開いた場合は、

  • 期限が切れてるので、サーバへ問い合わせを行う
  • 条件つきリクエスト(If-Modified-Since、If-None-Match)をサーバへ送ってくる

ただし条件つきリクエストを送ってくるのは、前回にサーバから Last-Modified、Etag を送ってある場合のみです。
またサーバ側は、もし If-Modified-Since、If-None-Match がクライアントから送られてきたら、変更ありなしを判断して 304レスポンスを返せば通信量が減らせます(Apacheなど普通のWEBミドルウェアなら静的コンテンツの場合は勝手に処理してくれるでしょうけど)。
サーバから304レスポンスを受け取った場合、ブラウザはローカルのキャッシュを利用します。

③ブラウザにキャッシュさせ、都度確認はそれほど必要ない

上記②の時から次のように変更すればいいです。

サーバからクライアントへのHTTP応答ヘッダ
Cache-Control "max-age=秒数" 例:86400など(この場合は1日)
Expires "ここに期限の日時"

その期限に達していない限り、ブラウザはサーバに問い合わせを行いません。
期限がきれた後の挙動は、②と同じです。

補足

iPhoneやAndroid等のネィティブアプリ内のWebViewはキャッシュが強いので、サーバからのキャッシュコントロールに関わらず、ローカルのキャッシュが利用されることがあります(恐らくWebViewの設定でキャッシュポリシーを変更できるかとは思います)。

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