ウェブサイトをgzip圧縮で高速化する
ウェブサイトをgzip圧縮を使って高速化するカスタマイズを紹介します。当サイトでもgzip圧縮を利用しています。
1.gzip圧縮によるウェブサイト高速化のイメージ
gzip圧縮によるウェブサイト高速化のイメージをご覧ください。
クライアント(ブラウザ)から、あるウェブサイトの「index.html」にアクセスしたとき、リクエストを受信したサーバでは、HTTPリクエストの分析や、「index.html」の圧縮ファイル「index.html.gz」の有無などをチェックして、圧縮ファイルが返却可能であれば「index.html.gz」を返却します。
返却できない場合は通常の「index.html」をレスポンスで返却します。
圧縮ファイルを返却できれば、データの転送量を減らすことができるので、これによりウェブサイトの高速化につながります。
圧縮ファイルは受信したブラウザ側で展開することができます。主要なモダンブラウザはほぼこの機能を有しています。
2.圧縮ファイル形式
圧縮ファイル形式はgzipです。ファイルの拡張子は「.gz」になります。deflate圧縮もありますが、本エントリーでは割愛しています。
gzip圧縮する方法については、以下の記事を参考にしてください。
gzipはLinuxコマンドです。
Windowsでgzipを利用する場合、UnxUtilsやUnxUpdatesをインストールすれば、コマンドプロンプトから利用可能になります。The gzip home pageからもツールをダウンロードできるようです。WinRARでも大丈夫みたいです。
Macはターミナルコマンドで普通に使えると思います。
3.圧縮可能なファイル形式
HTMLファイル、CSSファイル、JavaScriptファイルなどが圧縮可能です。
PHPも圧縮可能ですが、最初から圧縮された状態でサーバ上に配置していると肝心のサーバサイドPHP処理ができなくなるので、PHP処理を行ってから圧縮するという手はあるかもしれません。
WordPressであれば「GZIP Output」というプラグインがあります。
Movable Typeでは当ブログで「GzipFilePublisherプラグイン」を公開しています。
4.HTTPでgzip圧縮ファイルが利用可能な理由
1項で「圧縮ファイルは受信したブラウザ側で展開します」と書きましたが、そもそもブラウザが圧縮ファイルをサポートしている場合、HTTPリクエストに次のような「Accept-Encoding」ヘッダを付加します。
GET user-domain/index.html HTTP/1.1
Host: user-domain
User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:12.0) Gecko/20100101 Firefox/12.0
Accept: */*
Accept-Language: ja,en-us;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
上のリクエストは、要するに「(index.htmlについて)gzip圧縮やdeflate圧縮ファイルを受けつけられますよ」ということをサーバに伝えています。
このリクエストを受信したサーバは、圧縮ファイルを返却できる場合、次のような「Content-Encoding」ヘッダを付与したレスポンス(と圧縮したファイル)を返却します。
HTTP/1.1 200 OK
Date: Thu, 31 May 2012 10:02:44 GMT
Server: Apache/2.2.8 (Win32) DAV/2 mod_ssl/2.2.8 OpenSSL/0.9.8g mod_autoindex_color mod_fastcgi/2.4.6 PHP/5.2.5
Last-Modified: Sat, 16 Jun 2012 06:24:56 GMT
Etag: "8000000043450-25c3-4c111066fbeff"
Accept-Ranges: bytes
Content-Length: 9667
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/javascript; charset=utf-8
Content-Encoding: gzip
レスポンスを受信したクライアント(ブラウザ)は、Content-Encodingヘッダーを見て「gzip」と設定されているので受信したファイルをgzipファイルと認識して、展開します。
5.HTMLタグの書き方
調べていてよく分からなかったのがHTMLタグの書き方です。
CSSファイルやJavaScriptファイルを圧縮した場合、link要素やscript要素に圧縮ファイル名をそのまま書くものと思ってましたが、そうではないようです。
非推奨な例
<link rel="stylesheet" href="http://user-domain/style.css.gz" type="text/css" title="Default" media="screen,tv" />
<script src="http://user-domain/foo.js.gz"></script>
圧縮ファイルを利用する場合、HTMLタグの変更は必要ありません。
推奨する例
<link rel="stylesheet" href="http://user-domain/style.css" type="text/css" title="Default" media="screen,tv" />
<script src="http://user-domain/foo.js"></script>
6.圧縮ファイルを読み込む
では圧縮ファイルはどうやって読み込むのかというと、.htaccessを利用し、リクエストされたURLの末尾に「.gz」を付与して読み込みます。
.htaccessには次のような判定条件を設定します。
- HTTPリクエストで圧縮ファイルを許容しているか(=Accept-Encodingヘッダで「gzip」が許容されているか)
- HTTPリクエストの末尾が「.gz」でないか
- リクエストの末尾に「.gz」を付与したファイルがサーバに存在するか
すべての条件を満たした場合、リクエストURLの末尾に「.gz」を付与します。つまり圧縮ファイルが呼び出されたものとみなして圧縮ファイルを返却します。
条件を満たさない場合はURLの末尾に「.gz」を付与しません。
7..htaccessの解説
以下の内容を記述した.htaccessを用意し、サーバのディレクトリにアップロードします。サーバ上でviエディタ等で直接作成してもOKです。
書き方は色々あるので、他サイトの設定例も色々調べてみるといいでしょう。
RewriteEngine on
RewriteCond %{HTTP:Accept-Encoding} gzip
RewriteCond %{REQUEST_FILENAME} !\.gz$
RewriteCond %{REQUEST_FILENAME}\.gz -s
RewriteRule .+ %{REQUEST_URI}.gz
<files *.html.gz>
AddType "text/html;charset=utf-8" .gz
</files>
<files *.js.gz>
AddType "text/javascript;charset=utf-8" .gz
</files>
<files *.css.gz>
AddType "text/css" .gz
</files>
AddEncoding x-gzip .gz
6項の説明の繰り返しになりますが、設定内容の解説です。
まず、RewriteEngineディレクティブに「on」を設定することで、Webサーバ(Apache)での書き換えエンジンを有効にします。
1つめのRewriteCondディレクティブで、HTTPの「Accept-Encoding」ヘッダでgzipが許容されていれば次に進みます。gzipをサポートしていないブラウザなどからのリクエストで、このヘッダが付与されていなければ、ここで処理が終わって非圧縮ファイルを返却します。
RewriteCond %{HTTP:Accept-Encoding} gzip
2つめのRewriteCondディレクティブで、拡張子が「.gz」でなければ次に進みます。
RewriteCond %{REQUEST_FILENAME} !\.gz$
3つめのRewriteCondディレクティブで、元のファイルの末尾に「.gz」を付与したファイルが存在すれば次に進みます。
RewriteCond %{REQUEST_FILENAME}\.gz -s
上記3つの条件を満たしたリクエストについて、RewriteRuleディレクティブでURIの末尾に「.gz」を付与して処理をおこないます。
RewriteRule .+ %{REQUEST_URI}.gz
ファイル名の末尾が「.gz」のファイルについては、ファイル種別に応じて振り分けてAddTypeディレクティブでHTTPレスポンスの「Content-Type」ヘッダを付与します。HTMLファイルには「text/html」を、CSSファイルには「text/css」を、JavaScriptファイルには「text/javascript」を付与します。「charset=utf-8」は必要に応じて設定してください。
<files *.html.gz>
AddType "text/html;charset=utf-8" .gz
</files>
<files *.js.gz>
AddType "text/javascript;charset=utf-8" .gz
</files>
<files *.css.gz>
AddType "text/css" .gz
</files>
最後にAddEncodingディレクティブを使って、HTTPレスポンスに「Content-Encoging: gzip」を付与します。
AddEncoding x-gzip .gz
すでに.htaccessを使っている場合は、ファイルの末尾または先頭に上記の内容を追加してください。
8.gzip圧縮で通信されていることを確認する
Firefoxのアドオン「Live HTTP Headers」などで確認できます。
普通にリロードすると304が返却される可能性があるので、Windowsの場合は「Ctrl+F5」で強制リロードするとよいでしょう。
9.CDNサービスのファイルはgzip圧縮されている
ご存知かもしれませんが、Google CDNサービスなどはgzip圧縮されたファイルを返却します。
GET /ajax/libs/jquery/1.7.2/jquery.min.js HTTP/1.1
Host: ajax.googleapis.com
User-Agent: Mozilla/5.0 (Windows NT 6.0; rv:13.0) Gecko/20100101 Firefox/13.0.1
Accept: */*
Accept-Language: ja,en-us;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: keep-alive
Referer: http://user-domain/
Pragma: no-cache
Cache-Control: no-cache
HTTP/1.1 200 OK
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Type: text/javascript; charset=UTF-8
Last-Modified: Thu, 29 Mar 2012 18:19:50 GMT
Date: Thu, 14 Jun 2012 14:53:48 GMT
Expires: Fri, 14 Jun 2013 14:53:48 GMT
x-content-type-options: nosniff
Server: sffe
Content-Length: 33673
x-xss-protection: 1; mode=block
Cache-Control: public, max-age=31536000
Age: 344451
Google AnalyticsやGoogle Adsenseのコードも圧縮されています。
10.参考サイト
参考サイトは下記です。ありがとうございました。
- How to compress css & javascript: An alternative to mod_deflate or mod_gzip
- mod_rewrite でリクエストに応じて gzip 圧縮ファイルを返す
- .cssファイル、.jsファイルをgzip圧縮してみる
11.mod_deflateについて
本題からそれますが、はてなブックマークコメントで「mod_deflateじゃダメなの?」とありました。mod_deflateはサーバでコンテンツ圧縮を行うための機能です。
ざっと調べたところ、以下の理由により、一定の条件を満たす場合のみ有効であると思われます。
- レンタルサーバによってはmod_deflateが有効になっていない
- サーバで圧縮を行うため圧縮コストがかかる。
- 画像ファイルをBase64形式に変換するスクリプト
- 記事数を減らしてPV(ページビュー)を増やす方法
- Googleの「良質なサイト」を分析してみた
- CDNでウェブサイトを高速化するためのまとめ
- data URI Schemeを使ってHTTPリクエストを削減する
- Google検索結果の順位を上げる方法
- robots.txtを使って検索エンジンに不要なページをインデックスさせない方法