2016.10.21
2017.4.17

Webサイトのキャッシュ設定について

Webサイトのキャッシュの設定について、さんざん悩んで設定をコロコロ変えていましたが、結局、元に戻ったので、設定や調査した内容についてメモしておきます。

目次

  • サーバ(Apache)キャッシュ設定
  • クライアントのキャッシュ設定
  • HTML5のApplication Cache

サーバ(Apache)キャッシュ設定

「.htaccess」に追記。


ExpiresActive On
ExpiresByType image/gif "access plus 2 weeks"
ExpiresByType image/jpeg "access plus 2 weeks"
ExpiresByType image/png "access plus 2 weeks"
#ExpiresByType text/css "access plus 7 days"
#ExpiresByType text/javascript "access plus 7 days"
#ExpiresByType application/x-javascript "access plus 7 days"
#ExpiresByType text/html "access plus 7 days"

ここの設定で該当するファイルは期限が切れるまでサーバにアクセスすらしないらしいので、そうそう変わらない画像のみキャッシュの対象として設定。

html/js/cssは更新される可能性が高いので、対象から外しています。

上記のキャッシュ設定が利用できない場合、モジュールが有効になっていない可能性があるので、「httpd.conf」を開いて「expires_module modules/mod_expires.so」を有効にします。

参考:クラウド環境でのApacheの設定 | cloudrop

クライアントのキャッシュ設定

更新する可能性のあるファイルはクエリストリングを付加しておき、更新する際に明示的に値を変えます。


<html>
<head>
    <link rel="stylesheet" href="styles/main.css?20161020-001">
    <script src="scripts/app.js?20161020-001"></script>
</head>
<body>
</body>
</html>

この方法以外でなんとかできないものかといつも思いますが、個人的に明示的にキャッシュを更新する際はこれが一番正常に動作します。なので、あとはどれだけ自動化できるかだと思います。

また、AngularJSのテンプレートHTMLを利用する場合でも、同様な方法をとっておいた方がいいです。ルーティング(ui-router)を試していたら、指定したテンプレートHTMLをサーバから取得したりしなかったりと、動作に一貫性がありませんでした。

AngularJSでテンプレートHTMLを更新させる場合、リクエスト時のヘッダー情報である「If-Modified-Since」を書き換えてやる方法もあるみたいです。


var myApp = angular.module('myApp', []);
myApp.config(function($httpProvider){
    // Anti IE cache
    if (!$httpProvider.defaults.headers.get) 
        $httpProvider.defaults.headers.get = {};
    $httpProvider
      .defaults
      .headers
      .get['If-Modified-Since'] = (new Date(0)).toUTCString();
});

参考:IE 上での AngularJS の XHR GET 要求にて、キャッシュが効きすぎる件 : @jsakamoto

ただ、上記の方法では毎回新しいファイルをサーバから取得しまいます。それにjsファイルを$http.get()で取得している処理が動かなくなっていたこともあって(原因は未調査)、今のところ私は利用はしていません。

HTML5のApplication Cache

HTML5で利用可能なキャッシュの設定。

詳しくはこちら(HTML5のApplication Cacheを使う - Qiita)の記事を読むとよさげです。

ファイル名を指定してキャッシュできるのでライブラリ系をキャッシュしておくのによさそうと思いましたが、記事に書いてある通り非推奨になったようなので、今後の利用はやめておいた方が無難です。

ちなみに、このキャッシュの設定方法は以下の通りです。

「sample.appcache」


CACHE MANIFEST

# キャッシュしたいファイルを直接指定(「*.png」や「*.jpg」のようなワイルドカードでの指定はできない)
CACHE:
images/back_ground_img_header.jpg
lib/angular.min.js
lib/jquery.min.js
styles/bootstrap.min.css

#CACHEで指定したファイル以外でネットワークから読み込むファイルを指定(ワイルドカード利用可)
NETWORK:
*

# 代替コンテンツ
FALLBACK:
/ fallback.html

1行目の「CACHE MANIFEST」は必須。

上記アプリケーションキャッシュ「sample.appcache」を「index.html」に以下のように指定


<html manifest="sample.appcache">
<head></head>
<body></body>
</html>

このキャッシュを利用すると、ブラウザからWebサイトデータの消去をしない限り、キャッシュからファイルが読み込まれます。「F5リロード」やChrome開発者ツールの「キャッシュ消去とハード再読み込み」ではビクともしません。

また、見逃しがちですが、トップの「index.html」もキャッシュされます。Webサイトデータの消去をせずに更新するには「index.html」をキャッシュの管理に追加して、以下のようにファイル名に付加した更新用のクエリストリングを変更すると更新されました。


CACHE:
index.html?20161020-001

HTML5のApplication Cacheについては、オフラインでの動作を前提としていることなど、ちゃんと理解して使わないと意外なところで失敗しそうな感じがしました。

その他】関連記事