🌵

ブラウザキャッシュの仕組み

2023/04/09に公開

はじめに

最近Denoをよく触っており、DenoのSSRフレームワークであるFreshのミドルウェア・キャッシュについて調べている際にブラウザキャッシュのEtagヘッダが使用されており、気になったのでブラウザキャッシュの仕組みについて調べてみました。

Etagの正体

Etagとは、ブラウザキャッシュの仕組みの中で使用されるHTTPレスポンスヘッダーでリソースの特定のバージョンに関する識別子のことです。

Etagがあることでウェブサーバーは、コンテンツが変更されていない場合はレスポンス全体を再送する必要がないので、キャッシュがより効率的になる。

ブラウザキャッシュの設定について

ブラウザキャッシュを設定する際に必要なHTTPレスポンスヘッダーはEtagを含めて以下の通りです。

  1. Expiresヘッダー
  2. Cache-Controlヘッダー
  3. Last-Modifiedヘッダー
  4. Etagヘッダー

それぞれのHTTPヘッダーについて

Expiresヘッダー

Expiresヘッダーは、一度リソースを取得したら、Expiresに設定されている期限までは自動でブラウザ内部にキャッシュされます。
このキャッシュが消えるには、1. そもそもキャッシュされたファイル自体が消えるまたは、2. キャッシュの期限が切れる場合のみ。→強いキャッシュ。

Expiresヘッダーのキャッシュが一度有効になると、HTTPリクエストを送らなくなります。(期限内)
またクライアントとサーバで日付のずれが発生すると意図した通りに動かなくなるので注意です。

Cache-Controlヘッダー

このCache-Controlヘッダーは上記のExpiresヘッダーが抱えていた「サーバとクライアントのずれ」の問題を解消した強いキャッシュです。

max-age パラメーターでキャッシュの期限を秒数で指定することで、強制的にその期限内で一度有効になるとHTTPリクエストを送らなくなります。

下記の場合は一時間キャッシュを有効にします。

Cache-Control : max-age=3600

Last-Modifiedヘッダー

上記の二つのヘッダーとは異なり、このLast-ModifiedヘッダーはHTTPリクエストを送信しなくなることはありません。
このヘッダーが有効になると条件付きのGETリクエストを送信します。それによりレスポンスを小さくすることが可能です。

条件付きGETリクエストとは、クライアントが送信するHTTPリクエスト内に含まれている条件に合致すれば、HTTPサーバーは 304 Not Modified レスポンスを返します。
304 Not Modified レスポンスとは、ブラウザに対して「キャッシュを使用するように」と指示するためのstatus codeです。

Last-Modifiedヘッダーの挙動は下記のようになります。

  1. 初回のリソースの取得の際にサーバはレスポンスヘッダーに Last-Modified ヘッダー を付与します。
  2. 次に同じURLのリソースを取得するとき、ブラウザはHTTPリクエストヘッダーにIf-Modified-Sinceヘッダーを付与します。このレスポンスヘッダーが含まれたGETリクエストは、条件付きGETリクエストと呼ばれます。
  3. サーバーは、受信したリクエストのIf-Modified-Sinceヘッダーの値を確認して、そのURLのリソースの最終更新日がこのIf-Modified-Sinceヘッダーに指定した日時よりもあとだった場合には通常のHTTPレスポンスを返し、そうではない場合には 304 Not Modified レスポンスを返します。
  4. 304 Not Modifiedレスポンスを返すことでブラウザは、リソースの取得をキャッシュから行います。

Etagヘッダー

EtagヘッダーはLast-Modifiedヘッダーと同様に条件付きGETリクエストを送信することでキャッシュを実現します。

Etagヘッダーの挙動は以下のようになります。

  1. 初回のリソースの取得の際にHTTPサーバはEtagヘッダーに一意のハッシュを付与します。
  2. ブラウザはその受け取ったレスポンスのリソースファイルと、Etagハッシュをブラウザキャッシュに保存します。
  3. 次に同じリソースにアクセスする際に、ブラウザはリクエストヘッダーにIf-None-Matchに先ほどブラウザキャッシュに保存したEtagの値をセットしてリクエストを送信します。
  4. サーバで受け取ったIf-None-Matchのハッシュと初回アクセス時にセットしたEtagハッシュが一致した場合は、リソースの更新がないとみなし、304 Not Modifiedステータスをresponse bodyなしで返送し、キャッシュされたレスポンスのバージョンがまだ使用可能 (新しい) であることをクライアントに通知します。

補足

Last-ModifiedヘッダーとEtagヘッダーが混在した場合は、Last-Modifiedヘッダーは無視されEtagヘッダーが優先されます。

参考情報

https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/ETag
https://qiita.com/OmeletteCurry19/items/a84d6a7c91df50e7dcd6
https://numb86-tech.hatenablog.com/entry/2020/10/15/211914
https://uidev.jp/entry-104.html

Discussion