MEMORVA
ウェブサイト制作 HTML/JavaScript モバイル Linux 開発 サイト運営

.htaccessでブラウザキャッシュ、Cache-Control、Expiresの設定

更新:

ウェブブラウザは、一度表示したページのファイル(CSS、JavaScript、JPEGなど)をPCやスマホなどの端末側に保存する。 これをキャッシュという。 それらのファイルが更新されていない場合、キャッシュを利用してページを表示する。 ファイルの最終更新日時(last-modified)などを見て新たに取得するか判断する。

ウェブサイト側は、レスポンスヘッダに Cache-Control や Expires を追加することで、ブラウザがキャッシュする期間(期限)を意図的に制御できる。

ブラウザがキャッシュされたデータを利用すれば、サーバーへの無駄なリクエストが減らせる。 また、いちいちサーバーへファイルを見に行かないのでページが高速に表示される。 さらにデータ転送量も減らせる。

ブラウザはHTMLをダウンロードした後、その中で使われているCSS、JavaScript、画像などのファイルのダウンロードを開始する。 CSSをダウンロードする瞬間、たまたまサーバーのレスポンスが悪かったり、通信状態が悪かったりすると、CSSのダウンロードに時間がかかる。 CSSのダウンロード待ちの間、ページの表示が遅れる。

Googleは「PageSpeed Insights」やChromeのディベロッパーツールにあるLighthouseなど、ページの表示速度を計測するツールを提供している。 その中のアドバイスの1つにブラウザのキャッシュがある。 これらのツールでは詳しく解説されていないが、 ブラウザのキャッシュを活用する(PageSpeed Insights - Google for Developers) に解説がある。 他の項目についても解説があるので、表示速度に興味がある人は目を通しておいた方が良い。

Cache-Control

レスポンスヘッダに Cache-Control を追加するには .htaccess に以下のように記述する。

<IfModule mod_headers.c>
<FilesMatch "\.(css|js|gif|jpe?g|png|webp|svg|ico)$">
Header set Cache-Control "max-age=604800"
</FilesMatch>
</IfModule>

IfModule ディレクティブは、該当するモジュールがある場合のみ実行する。 ここでは mod_headers を利用している。

FilesMatch ディレクティブは、正規表現を使って対象とするファイル名の一致条件などが記述できる。 この例では、正規表現で拡張子が .css、.js、.gif などと一致する場合に実行している。 ここではCSS、JavaScript、画像などの主要な静的ファイルを対象としている。 HTMLは、PHPなどで動的に生成される場合もあるので除外している。

Header set Cache-Control "max-age=604800" で、Cache-Control をレスポンスヘッダに追加。 max-age はキャッシュする期間を秒数で指定する。 604800秒というのは 60×60×24×7 = 604800、要するに1週間(7日間)。

一部のレンタルサーバーではコントロールパネルからブラウザキャッシュを設定できるサービスもあるが、7日間に設定されていることが多い。

以下は、画像とCSS、JavaScriptを分けた例。

<IfModule mod_headers.c>
<FilesMatch "\.(gif|jpe?g|png|webp|svg|ico)$">
Header set Cache-Control "max-age=1209600"
</FilesMatch>
<FilesMatch "\.(css|js)$">
Header set Cache-Control "max-age=604800"
</FilesMatch>
</IfModule>

逆にキャッシュさせたくない場合は no-cache を指定する。

<IfModule mod_headers.c>
<FilesMatch "\.(css|js)$">
Header set Cache-Control "no-cache"
</FilesMatch>
</IfModule>

Expires

レスポンスヘッダに Expires を追加するには .htaccess に以下のように記述する。

<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType text/css "access plus 1 weeks"
ExpiresByType application/javascript "access plus 1 weeks"
ExpiresByType image/gif "access plus 2 weeks"
ExpiresByType image/jpeg "access plus 2 weeks"
ExpiresByType image/png "access plus 2 weeks"
ExpiresByType image/webp "access plus 2 weeks"
ExpiresByType image/svg+xml "access plus 2 weeks"
ExpiresByType image/x-icon "access plus 2 weeks"
ExpiresByType image/vnd.microsoft.icon "access plus 2 weeks"
</IfModule>

IfModule ディレクティブで mod_expires がある場合のみ実行している。

ExpiresActive On で有効化。

キャッシュさせたいファイルのMIMEタイプを ExpiresByType で指定。 MIMEタイプとは text/css などのこと。

JavaScript のMIMEタイプは text/javascript も併記している例も見られるが、私が使用している全てのレンタルサーバーで application/javascript となっていた。 心配な人は text/javascript も書いておくと良いかもしれない。

アイコン(.ico)ファイルは、多くのサイトで favicon.ico くらいにしか使われていないが、このMIMEタイプは一応 image/vnd.microsoft.icon となっている。 ただ、image/x-icon というMIMEタイプを設定しているサーバーもある。 私が使用しているレンタルサーバーでは、さくらのレンタルサーバは image/x-icon、エックスサーバーは image/vnd.microsoft.icon となっていた。

"access plus 1 weeks" は、ファイルにアクセスした時間からプラス1週間キャッシュさせるという意味。

weeks のほかに以下の type が使える。

type の指定は1つだけ書いた例が多いが、"access plus 2 weeks 3 days 5 hours" のように同時に複数並べて書くこともできる。 また、12 weeks のように 1 months など上位の範囲を超えた数字でも良い。

複数形だけでなく、month や week のように一応単数形でも動作する。 それどころか w など頭文字だけでも動作する。 ただし、months と minutes は頭文字が同じなので m だけだとエラー(Internal Server Error)になる。 mo や mi など2文字目まで書くと動作する。 正規の書き方ではないのでお勧めはしない。

plus は省略可能。

access のほかに、modification もある。 modification は、ファイルの最終修正時刻を基準にする。

weeks や months を使った書き方がよく紹介されているが、Apache公式によるとこれは代替期間指定構文と呼ばれている。 本来は以下のように書くようだ。

ExpiresByType text/css M604800
ExpiresByType image/gif A1209600

A または M に続けて秒数を書く。 A(access)はクライアントのドキュメントへのアクセス時刻、M(modification)はファイルの最終修正時刻。

ExpiresDefault

以下のように ExpiresDefault を使うとすべてのドキュメントに対してデフォルト値を設定できる。

ExpiresDefault "access plus 30 days" 

上書き

例えばレンタルサーバーで予めキャッシュ期限が決められていたとしても、.htaccessで独自にキャッシュ期限を書いた場合、それを上書きできる。 これはデフォルトの期限より長くしても短くしてもどちらでも上書きできる。

mod_headers と mod_expires どちらを使うか

最初に紹介した mod_headers は、レスポンスヘッダに任意のヘッダを追加・削除等を行うモジュールで、Cache-Control のためにあるわけではない。 例えば、以下のように独自のヘッダを追加することもできる。

<IfModule mod_headers.c>
<FilesMatch "\.(css|js)$">
Header set Example "a=1"
</FilesMatch>
</IfModule>

一方 mod_expires はキャッシュの制御のために使われるモジュール。 mod_expires を使用するとレスポンスヘッダには Expires が追加されるが、それだけでなく Cache-Control も自動的に追加される。 ヘッダは、ブラウザのディベロッパーツールなどで確認できる。 したがって、mod_expires を使えば mod_headers を使って Cache-Control を書く必要はない。

詳しくはApache公式サイト参照。

個人的にはキャッシュの設定は mod_expires だけ使用している。

さくらのレンタルサーバの強化

最近のレンタルサーバーは、コントロールパネルでブラウザキャッシュを設定できるサービスもある。 今のところ残念ながら、さくらのレンタルサーバにはその機能はない。 自分で .htaccess にキャッシュの設定を記述する必要がある。 ブラウザキャッシュがSEO(検索エンジン最適化)的にどの程度効果があるか分からないが、設定しておいて損はない。


はてなブックマーク X Bluesky