キャッシュに使用するヘッダーExpires/Cache-Control/Last-Modified/ETagの違いについて

キャッシュヘッダーの種類

Expires / Cache-Control max-age / ETag / Last-Modified これら4つのヘッダーを大きく分けるとキャッシュが有効であるかクライアントのみで判断可能なものと、毎回サーバーに問い合わせるものの2つがあります。

クライアントのみでキャッシュが有効か判断可能なヘッダー

ExpiresとCache-Control max-ageの2つはサーバーにリクエストを送らなくてもキャッシュが有効か判断できます。この為キャッシュが有効であればサーバーへのリクエストを送らなくても良いのでもっとも効率的です。ただし、アクセス自体なくなるのでアクセスログもでなくなります。

Expires

Expires: Mon, 29 Jan 2018 12:00:00 GMT

このように指定します。但しこれはキャッシュの有効期限を指定する為、常に値を更新していかないとキャッシュが効かなくなってしまいます。

Cache-Control max-age

Cache-Control: max-age=0

Cache-Controlではキャッシュに関係する設定がいくつかできるのですが、その中でもキャッシュの時間に関係するのがmax-ageです。Expiresでは常に値を更新していく必要がありますが、Cache-Controlで指定できるmax-ageではキャッシュする時間を秒で指定できます。

キャッシュを使用しても良いか毎回サーバーに問い合わせを行うヘッダー

ETagとLast-Modifiedはキャッシュを使ってもよいかを一度サーバーに問い合わせをするヘッダーです。キャッシュを使用してよいかどうかをサーバーに毎回問い合わせるのでパフォーマンスとしては問い合わせを行わないクライアントのみでキャッシュを使用するか判断できるヘッダーには劣りますが、サーバー側で自由に制御できるという利点があります(万が一間違えて設定していてもサーバー側でキャッシュを使用しないということができます)

ETag

ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"

Etagという文字列を使用してキャッシュを使用してもよいかサーバーにリクエストを送ります。一度データを取得していたらサーバーに

If-None-Match: "bfc13a64729c4290ef5b2c2730249c88ca92d82d"

のようなヘッダーを付与したリクエストを投げます。

If-None-Matchヘッダーに記入されたあと変更があればデータを送ってきますが、変更がなければ304(Not Modified)のステータスコードが返って来ます。この場合はブラウザの持っているキャッシュを使用します。

ETagの詳細はこちらの記事を参照

弱いETagと強いETag

ETagには強いETagと弱いETagがあります。

強いETagではバイトレベルで完全一致しており、範囲指定のリクエストの場合も完全一致しているのでキャッシュ可能なのでキャッシュします。

弱いETagではレスポンスのbodyが微妙に異なっていてもリソースの意味が変わらなければ同じとみなします。例えばレスポンスに時刻などが入る場合全くキャッシュができなくなってしまうのでこちらを使ったりする場合があるようです(そのような場合今はJavaScript使う場合が多いと思いますが)

また、ETagを使用する際にこのようにW/をETag文字列の前につけます。

ETag: W/"33a64df551425fcc55e4d42a148795d9f25f89d4"

Last-Modified

Last-Modified: Mon, 29 Jan 2018 12:00:00 GMT

最終更新日を使用してキャッシュを使用してもよいかサーバーにリクエストを送ります。一度データを取得していたらサーバーに

If-Modified-Since: Mon, 29 Jan 2018 12:00:00 GMT

のようなヘッダーを付与したリクエストを投げます。

If-Modified-Sinceヘッダーに記入されたあと変更があればデータを送ってきますが、変更がなければ304(Not Modified)のステータスコードが返って来ます。この場合はブラウザの持っているキャッシュを使用します。

優先度

これらのヘッダーには優先度があり複数設定されていた場合優先度の高いものが使用されます。

Cache-Control > Expires > Etag > LastModified

参照