[Web] Google Page Speedでサイトを高速化(1)
つい先日Googleから公開されたPage Speedは、彼らが社内で使っていたページを高速化するためのチェックツールです。Yahoo! YSlowのGoogle版と思えば良いのだと思います。
これらはあくまで「チェック」ツールなので、診断結果を自分で最適化しなければなりません。
YSlowでも「へー、知らなかった」と思うチェックポイントが幾つかありましたが、今回も考えていなかったようなポイント、知っていたものの徹底していなかった点などがあったので、そういった部分を中心に、自分の経験も踏まえてメモ。
まずは基本の「キ」である、ブラウザキャッシュについて。
ブラウザキャッシュの利用 – Leverage browser caching
基本的なことで忘れられがちですが、やはりブラウザキャッシュは最も効果的な高速化策のひとつです。
特にほとんど変更されない画像やCSS、Js、PDFなどの静的なコンテンツにはとても有効です。
また、HTMLファイルを静的コンテンツとみなすことも可能ですが、内実としては動的に作られていることも多く、細かな変更や修正も入るために一般的にはブラウザキャッシュはさせない方が良いでしょう。
ブラウザキャッシュを有効にする方法は、大きく分けると次の2種類があります。
- ExpireとCache-Control: max-age
これらのヘッダで提供されるキャッシュは、最新ファイルの確認すら行わないので、非常に高速です。一方で当然ながら、サーバ側で更新があってもクライアント側でそれが反映されません。 - Last-ModifiedとETag
こちらはExpireなどに比べれば弱いキャッシュで、ブラウザは2回目以降のリクエストでサーバにLast-ModifiedやETagを送信します。サーバ側ではこれらのリクエストが送られてくると手元のファイルと比較し、ブラウザが現在キャッシュしているコンテンツを使えば良いと判断した場合はステータス304を返し、コンテンツの内容は送信しません。これにより、サーバ側のディスクIOやネットワークトラフィックを軽減することができます。
これに対して、推奨される対応は次のようなものです。
- 全ての静的コンテンツにキャッシュ用ヘッダをつける
Googleは最低でも1ヶ月、出来れば1年以上の期間、ブラウザキャッシュを有効にするよう推奨しています。
これは、特にCSSやJsのようなファイルに対しては抵抗がある人も居ると思います。レイアウトが大きく狂ったり、スクリプトエラーが発生することを嫌って、全くキャッシュを効かないようにしているサイトもあるでしょう。
しかし、そういった場合でもfingerprintアルゴリズムなどを使って、ファイル名が変わるような対処をすべきとしています。
また、そのようにキャッシュを増やすとブラウザ側を汚してしまう懸念もありますが、通常は使われていないキャッシュは削除されていく仕組みがあるので、問題にはならないはずということです。 - fingerprintingを使った動的キャッシュ
ファイルが変更されるまで変わらないURLを用意してやれば、キャッシュ期間を大きくとってしまうことができます。
サーバ側でファイルが変更された場合にURLを変更(当然、呼び出す側のHTMLのscriptやlinkタグも変える)すれば、自動的にブラウザは新しいファイルを要求してきます。
この仕組みをどのように管理サイトに組み込むかは、各サイトの作り方によって工夫が必要です。
多少は運用が難しくなりますが、これを実装すればETagなどによる毎回の確認も不要になるので、トライする価値は大きなものがあります。 - VaryヘッダをInternet Explorer対応
Proxyサーバでのキャッシュを制御するためのVaryヘッダがありますが、IEでは問題があり、Accept-EncodingとUser-Agent以外のヘッダを指定するとブラウザで一切のキャッシュが行われなくなります。
Varyヘッダから他のフィールドを全て除去するか、Varyヘッダそのものを外してしまう必要があります。 - Firefoxでのキャッシュ衝突に注意
Firefoxのキャッシュファイル生成ロジックでは、パスの前後4文字ずつの計8文字しか使われません。そのため、比較的容易にハッシュ値が衝突してしまう可能性があります。前述のfingerprintingやアプリケーションでURLをジェネレートするような場合、この8文字ラインが異なるようにする必要があります。 - 複数サーバでのETag作成方法
ETagを用いる場合に、複数のWebサーバをロードバランシングしている環境では注意が必要です。多くのWebサーバではデフォルトの設定でETagの生成にi-nodeを用いるために、各サーバで同一ファイルに異なったETagをジェネレートします。結果、ラウンドロビンで割り振るとETagが全く役に立たない(転送量と確認が増える分だけ、むしろボトルネックになる)ようなことになります。そういった環境ではNASなどを用いてソースファイルを共有しているのでない限り、ETagの生成にはinodeではなくmtimeなどを利用するように設定すべきです。
これらの設定をApacheなどで行うドキュメントは山ほどあると思いますので、必要なら探してみてください。
このサイトではlighttpdを用いているので、せっかくですからlightyでのExpire設定方法を別途簡単に説明しておきます。
Related posts: