Google PageSpeed Insightsの結果
Webサイトのパフォーマンスを計測するツールとしてGoogleの提供する「PageSpeed Insights」が有名です。このツールを通して得られる問題点をクリアしていくことが、パフォーマンスを重視するGoogleに評価されるひとつの指標ともなっています。
前回の投稿で行った「HTML、CSS、JSファイルの圧縮」の後も、PageSpeed Insightsの結果として警告され続けていた問題点として「ブラウザのキャッシュを利用してください」というものがあります。
GoogleのPageSpeed Insightsの概要によると、静的なリソースをブラウザでキャッシュすると、ユーザーがサイトに複数回アクセスした場合に時間を節約できます。
ということです。
.htaccessでmod_expires設定
ブラウザでキャッシュさせるには、Apacheのmod_expiresモジュールを使います。.htaccessファイルに「MIMEタイプ」と「有効期限(アクセスしてからどれくらい保存させるか)」を以下のように記載します。
書き方のルールなどは以下を参考にしてください。
設定だけならこれで終わりとなりますが、実はここからいろいろやる必要が出てきます…
ファイル更新時の対策(ブラウザのキャッシュをクリアさせるには?)
諸刃の剣??
上記のように「.htaccessファイル」でキャッシュの設定を行うと、設定した期間内はブラウザのキャッシュを読み込むようになり、ページのパフォーマンスも向上します。
ただし問題もあり、キャッシュの期間内であれば常にキャッシュファイルが読み込まれるため、いくらJavaScriptやCSSのファイルを更新したとしても、新しい内容がページに反映されないということが生じてしまいます。
Google先生の見解
この事象について、GoogleのPageSpeed Insightsの「ブラウザのキャッシュを活用する」の項目では以下のように説明しています。
ときどき変更されるリソースの場合、サーバー上でリソースが変更され、サーバーがブラウザに新しいバージョンが提供されたことを通知するまで、ブラウザでリソースをキャッシュしておくことができます。リソースの各バージョンに一意のURLを指定すると、この方法を実現できます。
フィンガープリントを使うようにと続きます。たとえば、「my_stylesheet.css」というリソースがあるとします。このファイル名を「my_stylesheet_fingerprint.css」に変更できます。リソースが変更されると、フィンガープリントも変更されるため、URL も変わります。URL が変更されるとすぐに、ブラウザはリソースの再取得を強制されます。フィンガープリントを使用すると、頻繁に変更されるリソースでも、有効期限をそれより先の方の日付に設定できるようになります。
いわゆる「MD5」の使用を推奨しています。フィンガープリントの一般的な方法として、ファイルのコンテンツのハッシュをコード化した128ビットの16進数が使用されます。
解決方法は「ファイル名にフィンガープリント(MD5)をつける」
以上のように「更新したファイルのファイル名にフィンガープリントをつけて、ブラウザに新しいファイルだと認識させるようにしろ」とGoogle先生が仰っているので、ものは試せということでファイル名にMD5の付与対応をやってみることにしました。
説明に進む前に
これからファイル名にMD5を付与する方法を説明していきますが、Gruntを使うことを前提としています。Gruntのインストールの仕方などは以前書いた以下の記事を参考にしてください。
それから以下のような構成となっている2つのファイルを例として説明していきます。
<MD5付与前>
css/
┗ app.css
js/
┗ app.js
<MD5付与後>
assets/
┣ app-98f2b4256f620be0496ff18f157f863a.css
┗ app-28e80765706f3b2f9a96c2219c42dec6.js
MD5ハッシュ値の算出 – grunt-md5
Gruntでコンテンツ内容からMD5取得
「md5 grunt」でググると見事にありました。「grunt-md5」というGruntプラグインです。こいつを使ってみることにしました。
以下のコマンドでインストールします。
Gruntfile.jsには以下のように書き込みます。
[grunt]コマンドを実行するとそれぞれ、以下のファイルがassetsディレクトリ内に作られます。
- app-98f2b4256f620be0496ff18f157f863a.css
- app-28e80765706f3b2f9a96c2219c42dec6.js
これでファイル名にMD5を付与したファイルを作ることができました。
HTMLファイルの書き換え – grunt-text-replace
ファイルの準備ができたら、次はこれらのファイルを読み込めるように、HTMLファイルの中のファイルを読み込んでいる部分を変更しなければいけません。ただ毎回手動でやるのは面倒くさいです。そこで再びGruntの登場ですが、これが意外と大変でした。
grunt-text-replaceを使う
まず、HTMLファイルの内容を置換させるのは「grunt-text-replace」というGruntプラグインを使えば実行可能です。
以下のコマンでインストールします。
Gruntfile.jsの書き方
Gruntfile.jsファイルの書き方は以下の通りです。まずプラグインを読み込みます。
実行するタスク部分(基本スタイル)
どうやってMD5を付与したファイル名を取得するのか?
Gruntfile.jsでの設定において、置換前の部分は正規表現で書けます。置換させるファイル名、これはgrunt-md5で自動的にMD5がファイル名に付与されるので、変更された後のファイル名を動的に取得できるようにしておかなければなりません。
なんかGruntでのうまいやり方が見つからなかったので、Node.jsのfsモジュールを使って取得するようにしました。以下のようなfileオブジェクを作って、Gruntfile.jsに追加しました。
上記の処理をファイル名を置換させるタスクの部分で実行させるようにします。
再びGruntfile.jsの書き方
上記を踏まえて、Gruntfile.jsを書くと以下のようになります。
先ほどのgrunt-md5のタスクと組み合わせると、1.ファイル名にMD5を付与し、2.HTMLファイルの読み込み部分を書き換えるタスクが完成します。
旧ファイルの削除 - grunt-contrib-clean
ところが、grunt-md5をタスクを繰り返し行っていると、assetsディレクトリの中に同じ形式のファイル名を持ったファイルがどんどん増えていきます。上記のgrunt-text-replaceを使ったタスクで置換させるファイル名を取得する際に、最新のファイルのファイル名が取得できないという問題が発生します。
これを解決する簡単な方法として、grunt-md5のタスクを実行する前に、古いファイルは全て削除するようにしました。
grunt-contrib-cleanを使う
任意のファイルを削除するには、「grunt-contrib-clean」というGruntプラグインを使います。
以下のコマンでインストールします。
Gruntfile.jsの書き方
こちらはだいぶシンプルに書けます。
これで古いファイルは全て削除されるようになります。
一連の作業の自動化(完了)
行うべきタスクはすべて出揃ったので、後は対象のファイルが更新されるたびにすべてのタスクが自動で実行されるようにしてみます。
ファイル状態の監視
ファイル状態を監視するには、おなじみ「grunt-contrib-watch」というGruntプラグインを使います。
以下のコマンでインストールします。
Gruntfile.jsの書き方(完成版)
以下は、grunt-contrib-watchの書き方とともに上記のタスクも全て含めたGruntfile.jsの書き方となります。
だいぶ長くなって何の話か忘れそうになりますが、以上がGruntを使った「ブラウザのキャッシュをクリアさせるために、ファイル名にフィンガープリント(MD5)をつける」方法となります。興味があったらお試しください。
後編では、別のやり方を紹介します。
コメント