ブラウザキャッシュについての備忘録

今回はブラウザキャッシュについて、調べたので、ブラウザキャッシュについて自分に対する備忘録としてまとめていきたいと思います。

ブラウザキャッシュとは

ブラウザキャッシュとは、一度アクセスしたサイトのデータ(HTMLやCSS, JavaScript, 画像など)をブラウザで一時的に保存しておく仕組みです。一時的にデータをブラウザに保存することで、次回読み込んだときにHTTPリクエストをせずに保存したデータを使用してWebサイトを表示することができます。ブラウザキャッシュを活用することで、HTTPリクエストの数を減らしたり、HTTPレスポンスのサイズを小さくすることができるとっても便利な機能なんです。うまく利用することで2回目以降の読み込み時間を大幅に減らすことができます。

ブラウザキャッシュの設定はHTTPヘッダーを利用して設定することができますが、キャッシュの設定で利用できるHTTPヘッダーにはいくつかの種類があります。

  • Expires ヘッダー
  • Cache-Control ヘッダー
  • Last-Modified ヘッダー
  • ETag ヘッダー

上記4種類のヘッダーがブラウザキャッシュの設定で利用できるHTTPヘッダーです。これらのヘッダーはそれぞれ強いキャッシュ弱いキャッシュです。
Expires ヘッダーとCache-Control ヘッダーは強いキャッシュを設定するためのHTTPヘッダーで、Last-Modified ヘッダーとETag ヘッダーは弱いキャッシュを設定するためのHTTPヘッダーです。
それぞれの特徴や使い分けについて説明していきます。

Expires ヘッダーの設定

Expires ヘッダーによるキャッシュは、一度リソースの取得を行うと期限が切れるまで自動的にブラウザ内部にキャッシュされます。キャッシュされたファイルが消えるか、期限が切れるまではブラウザ内部にキャッシュされ続ける強いキャッシュです。
Expires には以下のように期限となる日時を指定します。

Expires: Mon, 02 Oct 2021 13:19:30 GMT

この期限が切れるまでは、ブラウザは一度リソースを取得するとキャッシュを保持します。このキャッシュは1度有効になるとHTTPリクエストをしないようになります。
Expires ヘッダーは、Apacheウェブサーバーでは次のように設定できます。

ExpiresActive on
ExpiresByType image/png                             "access plus 1 month" # png画像は1ヶ月キャッシュ
ExpiresByType text/html                             "access plus 1 days" # HTMLは1日キャッシュ

Expires ヘッダーには注意点があります。キャッシュの期限を日時で指定するため、サーバーとクライアントの時間設定がずれている場合にキャッシュの期限が正しく意図道理に設定されません。

Cache-Control ヘッダーの設定

Cache-Control ヘッダーを設定することで、強いキャッシュを有効にすることができます。つまり、Expires ヘッダーによるキャッシュと同じで、1度有効になるとHTTPリクエストをしないようになります。
Cache-Control ヘッダーはExpires ヘッダーのキャッシュ期限を日時で指定する問題を解消しており、次のように max-age パラメーターでキャッシュの期限を秒数で指定できます。

Cache-Control : max-age=600

この例では600秒間リソースをキャッシュします。
ApacheウェブサーバーでCache-Control ヘッダーを付与するにはExpiresActiveディレクティブとExpiresByType ディレクティブを記述することでExpires ヘッダーとCache-Control ヘッダーが自動的に付与されます。

Expires ヘッダーとCache-Control ヘッダーですが、ブラウザはExpires ヘッダーとCache-Control ヘッダー両方が設定されるとCache-Control ヘッダーを優先します。これは、Cache-Control ヘッダーのほうが登場が遅かったためです。

URLを擬似的に付与する

先述の2種類のキャッシュは強いキャッシュであり、キャッシュの期限が切れるかキャッシュファイルが削除されるまでHTTPリクエストを出さなくなります。この性質はキャッシュするファイルが全く変わらないか、殆ど変わらないには有効ですが、内容が変更されがちなファイルには少し不都合です。

このキャッシュを擬似的にクリアするためのテクニックが、キャッシュバスティング と呼ばれるテクニックです。
キャッシュバスティングとは、リソースのURLに対してトークンを付与することです。

例えば、bundle.js というjsファイルがあるとします。このファイルの強いキャッシュをクリアするために以下のようにトークンを付与します。

<script src="bundle.js?202110020055" ></script>

トークンを付与することでブラウザはリソースが異なると認識し、キャッシュが解除されます。
PHPなどのサーバースクリプトで正しく設定することでトークンの付与を自動化することができます。

Last-Modified ヘッダー

Last-Modified ヘッダーによるキャッシュはHTTPリクエストを送信しなくなるわけではありません。キャッシュが有効になると、Last-Modified ヘッダーは、HTTPリクエストを送信しない代わりに、条件付きGETリクエスト を出すことでHTTPレスポンスを小さくできます。条件付きGETリクエストとは、クライアントが送信するHTTPリクエスト内に含まれている条件に合致すれば、HTTPサーバーは 304 Not Modified レスポンスを返します。304 Not Modified レスポンスとは、キャッシュを使用してねという意味です。

Last-Modified ヘッダーの詳しい動作は以下になります。
ブラウザがあるURLのリソースを初めて取得したとき、サーバーはそのHTTPのレスポンスヘッダーに Last-Modified ヘッダー を付与します。

Last-Modified: Wed, 06 Oct 2021 04:58:88 GMT

そして、次に同じURLのリソースを取得するとき、ブラウザはHTTPリクエストヘッダーに次のような If-Modified-Since ヘッダーを付与します。このレスポンスヘッダーが含まれたGETリクエストは、条件付きGETリクエストと呼ばれます。

If-Modified-Since: Wed, 06 Oct 2021 04:58:88 GMT

ウェブサーバーは、受信したリクエストの If-Modified-Since ヘッダーの値を確認して、そのURLのリソースの最終更新日がこのIf-Modified-Since ヘッダーに指定した日時よりもあとだった場合には通常のHTTPレスポンスを返し、そうではない場合には 304 Not Modified レスポンスを返します。304 Not Modified レスポンスを返すことでブラウザは、リソースの取得をキャッシュから行います。

ETag ヘッダー

ETag ヘッダーでも Last-Modified ヘッダーと同様に条件付きGETリクエストによる弱いキャッシュを利用できます。
Last-Modified ヘッダーとの違いは、 ETag ヘッダーはHTTPリクエストで取得するURLのリソースのバージョン(エンティティタグ)により、304 Not Modified レスポンスを返してキャッシュを利用するかどうかを判断します。

ETag ヘッダーの動作は以下になります。

ブラウザがあるリソースに対して初めてアクセスしたとき、HTTPサーバーはレスポンスヘッダーに以下のようなEtag ヘッダーを生成します。ETag ヘッダーに指定されている値は一意のIDです。

ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"

ブラウザは、取得したファイルと、ETagを保存しておきます。そして、次に同じURLのリソースにHTTPリクエストを送信するとき、ブラウザはHTTPリクエストヘッダーの中に If-None-Match ヘッダーを送信します。If-None-Match ヘッダーの値は先程のETagの値です。

If-None-Match: "33a64df551425fcc55e4d42a148795d9f25f89d4"

HTTPサーバーは、クライアントからIf-None-Match ヘッダーを受け取るとリソースの現在のETagの値と比較します。同じであればリソースの変更がないとみなし、304 Not Modified レスポンスを返し、ブラウザはキャッシュを利用します。

Apache ウェブサーバーでは以下のように設定することで ETag を付与することができます。

FileETag INode MTime Size

また、以下のように設定することで ETag ヘッダーを付与しないようにすることができます。

FileETag None

また、HTTPレスポンスヘッダーに Last-Modified ヘッダーとETag ヘッダーの両方を設定した場合にはLast-Modified ヘッダーは無視され、ETag ヘッダーが優先されます。ETag ヘッダーを使用したキャッシュはトークンさえあっていれば複数の結果をキャッシュできるため、Last-Modified ヘッダーでのキャッシュよりも柔軟に扱うことができるからです。

ETag ヘッダー によるキャッシュには1つ欠点があります。複数マシンで構成しているサーバーだと、同じデータでもデータ配信サーバーが異なると ETag が一致しない点です。この点には気をつけましょう。

まとめ

ブラウザのキャッシュについてまとめてみました。普段よく耳にするキャッシュという言葉ですが、更に深ぼってみることで、更に解像度が上がった気がするのでちゃんと調べてみてよかったです。それでは次のブログでお会いしましょう。!