【Apache】キャッシュについて(ETagとLast-Modifiedの意味と設定方法)
Apacheを使って、キャッシュを設定する方法を紹介します。
そもそもキャッシュとは何か、どんなものがあるのか、
それの設定方法やキャッシュの仕組みも含めて説明します。
キャッシュとは
キャッシュは、主に二種類に分けられます。
一つは、ブラウザ側にキャッシュを保存するものです。
画像、CSS、JavaScriptなどをブラウザに保存します。
そのため、ブラウザ内部に保持されたものを表示します。
もう一つは、サーバー側にキャッシュを保存するものです。
いろんなパターンがありますが、一つはメモリ上にファイルなどを読み込みそれをキャッシュとして使います。データベースなどからデータを読みよってメモリ上に置いておくのもキャッシュです。
他にもphpの実行結果などをhtmlとしてどこかのフォルダに生成しておいて、それをリクエストのレスポンスとして返却するといったキャッシュもあります。
ブラウザ側のキャッシュ制御
ブラウザ側のキャッシュ制御には、2種類あります。
- ETagの変更を検知
- Last-Modifiedの変更を検知
ETagによって変更を検知する方法は、INodeと変更日時とファイルサイズで変更があったかを判定します。
INodeというのは、ファイルに付与されている属性情報です。ファイルの編集者であったり、アクセス権限だったり、ファイルごとに一意の番号が振られています。ETagはその番号を使用します。
Last-Modifiedによって変更を検知する場合は、最終更新日時で判定します。
[FileETag]を使ったキャッシュの設定
コンテキストは、サーバ設定ファイル, バーチャルホスト, ディレクトリ, .htaccessです。
ETagを使うためには、[FileETag]を使用します。
[FileETag]を使うことで、変更検知に必要な情報、つまりINode、更新日時、ファイルサイズを使用できます。
INode、更新日時、ファイルサイズを使用したいとき
# INode、更新日時、ファイルサイズを使用
FileETag All
FileETag INode MTime Size
すべてのコンテキストで有効なので、どこにでも記載できます。
ETagを使用しないとき
# ETagなし
FileETag None
更新日時、ファイルサイズのみ使用したいとき
# 更新日時、ファイルサイズのみ使用
FileETag MTime Size
ETagの確認方法
検証ツールのNetworkタブを開き、ctrl+shift+R もしくはcommand+shift+Rでハードリセットします。
Response HeadersのETagというパラメータがあります。
そのETagはサーバーからブラウザに返却されたナンバーです。
次にブラウザからサーバーに対してリクエストを送信する際に、そのETagのナンバーをRequest Header内に記述してサーバーに送ります。
Request HeadersのIf-None-Matchというパラメータに先程のETagのナンバーが設定されます。
ctrl+Rもしくはcommand+Rでもう一度リクエストを送ると、Statusコードが304となっています。
304はキャッシュを使っているときにでるステータスコードです。
サーバー側がIf-None-MatchのナンバーとETagのナンバーを確認して一致するものがあれば304ステータスでレスポンスを返します。
ちなみに304ステータスのときは、Headerしか返ってこず、bodyは返ってきません。
Last-Modified(Expires)を使ったキャッシュの設定方法
<IfModule mod_expires.c>
ExpiresActive On
<FilesMatch "\.(png|jpe?g|gif|css|js|html)$">
# アクセスしてから2週間
ExpiresDefault "access plus 2 week"
# ファイルが編集されてから2週間
# ExpiresDefault "modification plus 2 week"
</FilesMatch>
</IfModule>
# キャッシュ期間の指定方法
# 年:year(s)
# 月:month(s)
# 週:week(s)
# 日:day(s)
# 時:hour(s)
# 分:minute(s)
# 秒:second(s)
上のようにして記述します。
[ExpiresActive]のコンテキストは、サーバ設定ファイル, バーチャルホスト, ディレクトリ, .htaccessです。
[ExpiresDefault]のコンテキストは、サーバ設定ファイル, バーチャルホスト, ディレクトリ, .htaccessです。
accessとすれば、アクセスしてからですし、modificationとすれば、ファイルを編集してからのキャッシュの期間を指定することができます。
FilesMatchで右にある正規表現にマッチした場合にキャッシュが適用されます。
Last-Modified(Expires)を使ったキャッシュの確認方法
やり方はEtagと同じで、
Response HeadersのCache-Controlを確認します。
Cache-Controlにmax-age=1009600のようにその期間が記載されています。
max-ageの左辺は秒数です。1009600/24/60/60 = 14days
また、Last-Modifiedパラメータにも、accessならアクセスのあった最終日時がセットされています。modificationなら最終変更日時がセットされます。
1回目の通信ではRequest Headersではこの情報は知らないため記載はありません。
2回目の通信をしたとき、304ステータスでキャッシュが利用されていることがわかり、Response Headersは先程と同じになります。
Request Headersには、If-Modified-Sinceパラメータがセットされ、そこにaccessならアクセスのあった最終日時がセットされます。
このIf-Modified-Sinceの値をサーバー側で確認し、設定した期間(上の例なら2週間)以内であれば304ステータスを返します。
実務的な設定
<IfModule mod_expires.c>
ExpiresActive On
<FilesMatch "\.(png|jpe?g|gif|css|js|html)$">
# アクセスしてから6ヶ月程度
ExpiresDefault "access plus 6 months"
</FilesMatch>
</IfModule>
Last-Modifiedは長めに設定することが推奨されています。
ただし、変更があった場合、その変更を反映させたいので、phpファイルに以下のように変更します。
<body>
<script src="index.js?v1"></script>
</body>
上のように、?v1のようにしてパラメータとしてバージョンをわたします。
変更を知らせるために、?v1を?v2にします。
ブラウザではこの数字が変わったタイミングで変更を検知することができます。
ブラウザはURL単位で保持しているので、パラメータ部分でもURLが変わると変更を検知することができます。