gzip 圧縮によるサイトパフォーマンスを向上させる方法

公開日:
更新日:
0ハイパフォーマンスWEB

gzip 圧縮とは

gzip 圧縮とは、ファイルサイズを小さくする圧縮方法の1つです。gzip 圧縮を取り入れることで、ユーザと Web サーバ間でやりとりされている HTML ドキュメントのファイルサイズが小さくなり、転送速度が向上します。


gzip 圧縮の特性として、ファイル内に同じ文字列が多いほど圧縮率が高まります。HTML ドキュメントファイルは、空白、タグ、スタイルなど同じ文字列が多く含まれているため、高い圧縮率を得られます。


ただし、gzip 圧縮の高い圧縮率を得るために不要な空白・改行の除去、タグの種類を限定するなど過剰な最適化は、Web ページの可読性、保守性を損なうため、適度なバランスで最適化することが大切です。

gzip 圧縮の利用可否を通知する

クライアント側のブラウザが gzip 圧縮を利用可能である場合、HTTP リクエスト内の Accept-Encoding ヘッダでサーバ側に通知します。サーバ側では、どのような方法で応答を返すか HTTP レスポンス内の Content-Encoding ヘッダでクライアント側に通知します。


# HTTP Request
HTTP/1.1
・・・ 中略 ・・・
Accept-Encoding: gzip, deflate, sdch

# HTTP Response
HTTP/1.1 200 OK
・・・ 中略 ・・・
Content-Encoding: gzip
 gzip 圧縮の利用可否を通知する

上記の例では、クライアントがサーバに対して gzip, deflate, sdch の 3 種類の圧縮コンテンツの受け入れが可能であることを通知しています。サーバはクライアントに対して gzip でレスポンスを返すことを通知しています。Accept-Encoding ヘッダーが空の場合、どの形式でレスポンスを返すかはサーバに委ねられます。

gzip 圧縮の対象コンポーネント

gzip 圧縮の対象コンポーネントは、テキストファイル全般に有効です。HTML, CSS, Javascript などを gzip 圧縮するとよいでしょう。ただし、画像や pdf などの圧縮済みコンポーネントを gzip 圧縮すると、ファイルサイズが増えて逆効果になる場合もあるため、全てのコンポーネントを gzip 圧縮するべきではありません。圧縮するコンポーネントを選別するには、FilesMatch ディレクティブや、RewriteCond ディレクティブなどを使用しましょう。


ファイルの内容にもよりますが、gzip の圧縮率は約 60 ~ 70 % 程度得られます。gzipは圧縮レベルがあり、圧縮レベルを上げることでファイルサイズを更に小さくすることもできます。ただし、圧縮レベルも上げても大幅な圧縮率は得られず、サーバの CPU リソースも多く消費するため、圧縮レベルはデフォルト値がよいでしょう。


もしも、圧縮レベルを変更する場合は、DeflateCompressionLevel ディレクティブで 1 (低圧縮) ~ 9 (高圧縮) の範囲で変更可能です。デフォルト値の圧縮レベルは 6 になっています。ただし、変更は .htaccess では設定できないため、httpd.conf を編集権限を持つユーザに限られます。

gzip 圧縮を有効にする方法

gzip 圧縮を有効にするには、".htaccess" で設定します。設定方法には大きく分けて 2 種類あり、"mod_deflate" モジュール、または "mod_rewrite" モジュールのどちらかを利用します。

mod_deflate モジュールを利用する

mod_deflate モジュールは、クライアント側からアクセスがある毎に、サーバ側で転送するコンポーネントを自動で圧縮してくれるモジュールです。非常に便利なモジュールですが、サーバの負荷が高くなるため、レンタルサーバによっては提供していない場合もあります。mod_deflate モジュールが提供されており、有効にするためには、以下のように記述します。


# mod_deflate を有効にする
SetOutputFilter DEFLATE

# レガシーブラウザは gzip 圧縮を行わない
BrowserMatch ^Mozilla/4 gzip-only-text/html
BrowserMatch ^Mozilla/4\.0[678] no-gzip
BrowserMatch \bMSI[E] !no-gzip !gzip-only-text/html

# 画像ファイルはgzip圧縮を行わない
SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png|ico)$ no-gzip dont-vary

# プロキシサーバ用の設定
Header append Vary User-Agent env=!dont-vary
 mod_deflate モジュールを有効にする(Apache 2.x)

さくらインターネットでは、mod_deflate モジュールは非公開ですが、利用可能な状態で提供されています。 ヘルプデスクに問い合わせた結果、"非公開の機能であるため利用方法のサポートは行っておらず、予告なしに利用ができなくなる場合もある" とのことでした。また、さくらインターネットでは上記の記述方法では mod_deflate が有効になりません。 有効にするためには、以下のように記述します。


# mod_deflate を有効にする
SetOutputFilter DEFLATE

# Accept-Encoding を無視して強制的に gzip を返す
SetEnv force-gzip
 さくらインターネットで mod_deflate モジュールを有効にする

force-gzip は特別な環境変数です。DEFLATE フィルタが使用するように設定されているときに、この環境変数はブラウザの accept-encoding の設定を無視して常に圧縮された出力を送るようにします。この方法であれば、さくらインターネットでも gzip 圧縮を行うことが可能です。

mod_rewrite モジュールを利用する

mod_rewrite モジュールは URL を書き換える機能を持つモジュールで、アクセスされた URL を gzip ファイルの URL に書き換えることで、mod_deflate モジュールと同等の機能を提供します。ただし、mod_deflate モジュールと異なり、gzip 圧縮ファイルをユーザ側で用意する必要があります。また、以下の設定例では、圧縮前のファイル名と同名の gzip ファイルを用意する必要があります。(例えば、index.html では index.html.gz )


# RewriteEngineを 有効にする
RewriteEngine on

# gzip を提供する条件
RewriteCond %{HTTP:Accept-Encoding} gzip
RewriteCond %{REQUEST_URI} (\.js|\.css|\.html)$
RewriteCond %{REQUEST_FILENAME}.gz -s
RewriteRule .* %{REQUEST_URI}.gz [L]

# ファイル別に MIME タイプを設定
<FilesMatch "\.html?\.gz$">
  ForceType text/html
</FilesMatch>
<FilesMatch "\.css\.gz$">
  ForceType text/css
</FilesMatch>
<FilesMatch "\.js\.gz$">
  ForceType text/javascript
</FilesMatch>
 mod_rewrite モジュールによる gzip ファイルの提供

ただし、さくらインターネットでは、上記の例でうまくいかない場合があります。 その場合、5 行目の Accept-Encoding を判定している条件を削除すると成功します。詳細は不明ですが mod_deflate の結果を踏まえると HTTP リクエストの Accept-Encoding を破棄している可能性があります。以下は、Perl でテストした結果です。


#!/usr/bin/perl

use strict;
use warnings;
use LWP::UserAgent;

# Accept-Encodingにgzipを付与
my $ua = LWP::UserAgent->new;
$ua->default_header('Accept-Encoding' => 'gzip');

# HTTP Responseを受信
my $url = "https://murashun.jp/";
my $request = new HTTP::Request(HEAD => $url);
my $header = $ua->request($request);

print $header->as_string;
 PerlでHTTPレスポンスを受け取るサンプルコード

# %{HTTP:Accept-Encoding} gzip 付与
HTTP/1.1 200 OK
Content-Length: 1548 # 圧縮されていない(・ω・;

# %{HTTP:Accept-Encoding} gzip 削除
HTTP/1.1 200 OK
Content-Encoding: x-gzip
Content-Length: 725  # 圧縮されている(・ω・*
 実行結果

gzip 圧縮ファイルの作り方

これ以降の gzip 圧縮ファイルの作り方についての説明は、mod_rewrite モジュールを利用する方への説明です。mod_deflate モジュールが利用可能な場合は、"gzip 圧縮されているか確認する方法" まで読み飛ばしても大丈夫です。


gzip 圧縮ファイルの作り方は、gzip 形式に対応したフリーソフトを利用する方法が最も簡単です。圧縮する前に、対象コンポーネントの文字コードが "UTF-8(BOMなし)"、改行コードが "LF" になっていることを確認しましょう。文字コードと改行コードが誤っている場合、gzip 圧縮ファイルを読み込めない場合があります。


しかし、gzip 圧縮ファイルは対象コンポーネントの追加や変更をするたびに作り直してサーバにアップロードする必要があるため、非常に手間です。そのため、サーバ側で gzip 圧縮ファイルを一括で作成するシェルを用いると便利です。


#! /usr/local/bin/bash

PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin
TYPE=( "*.html" "*.css" "*.js")
DIR="/home/murashun/www"

for cdir in $DIR
do
  for i in "${TYPE[@]}"
  do
    find $cdir -iname "$i" \
    -exec bash -c 'A={};B={}.gz; gzip -fc $A > $B;' \;
  done
done
 gzip圧縮ファイルを作るシェル

4 行目に gzip 圧縮する対象コンポーネントを指定、5 行目にディレクトリパスを指定します。実行すると、ディレクトリパス配下に保存された対象コンポーネントを同名で gzip 圧縮します。例えば、index.html の場合は index.html.gz になります。また、圧縮する元ファイルは削除されません。

gzip 圧縮ファイルの作成を自動化する

ここからは更に発展的なプロセスですが、CRON を使うことにより gzip 圧縮ファイルの作成が自動化できます。CRON とは、特定のコマンドを定期的に実行する機能で、さくらインターネットのレンタルサーバーでは "スタンダード" 以上のプランから利用できます。 ただし、CRON の設定や実行するプログラムによってはサーバーに負荷がかかり、サーバーを共有している他のユーザに影響を与える場合がありますので、利用には注意が必要です。


CRON でシェルを実行するには、パーミッションを "700(rwx------)" に設定します。そして、一般的には crontab コマンドで CRON の設定をしますが、さくらインターネットではサーバコントロールパネルで CRON を設定できますので、そちらで設定していきます。


左のメニューから "アプリケーションの設定" の中にある "CRONの設定" をクリックし、">> 新規項目の追加" を選択します。


CRON設定
CRON設定


"実行コマンド" に以下を設定します。コマンドパスや、ディレクトリパスなどは実行環境によって変更して下さい。


/usr/local/bin/bash /home/murashun/www/sh/gzip.sh
 CRON の設定

CRON の実行間隔は対象コンポーネントの量や更新頻度によって異なるため、サーバに負荷がかからない程度に設定して下さい。また、対象コンポーネントを更新して動作を確認する際は、CRONを停止するか、.htaccess を書き換えることで、即時反映されます。更新が終わったら、設定を元に戻しておきましょう。

gzip 圧縮されているか確認する方法

すべての設定が完了したら、反映されているかチェックしましょう。Webサイトのパフォーマンスを測定するサイトを使うと簡単にチェックできます。


PageSpeed Insights
GTmetrix

まとめ

Web サイトのパフォーマンスはSEO的にも有利とされていますが、ユーザビリティの観点からもページが素早く表示されるのは気持ちがいいものです。ユーザに余計なストレスを与えないように、Web サイトのパフォーマンスは適度にチューニングするのがよいでしょう。