Nginxのhttp_gzip_static_moduleで高速化

nginx_gzip

せっかくNginxを導入したのでgzipやproxy cacheで高速化をしないとつまらないので、まずはNginxのGzipモジュールのhttp_gzip_static_moduleを試してみました。思っていたより読み込み速度が改善したので今回はそれについての設定メモです。

Module ngx_http_gzip_static_module

今回は以下のサイトを参考にしました。ありがとうございました。



上記のサイトによると、デフォルトのngx_http_gzip_moduleだとリアルタイムで圧縮処理を行うためその分時間がかかってしまい、今回のhttp_gzip_static_moduleの方が高速ということです。

ただ難点としては

  1. Nginxのインストール時にオプションに–with-http_gzip_static_moduleを指定していないと使えない
  2. 事前にgzipコマンドでファイルを圧縮しておかなければいけない

などがあります。1についてはインストールされてなければどうしようもないですが、2については素晴らしいシェルを書いている方がいたのでそれを利用しました。

http_gzip_static_moduleを使えるようにする

1. モジュールがインストールされているかチェック

このブログのNginxはUbuntu12.04で

sudo apt-get install nginx

でインストールしているだけなのでモジュールのオプションはaptにおまかせです。以下のコマンドでhttp_gzip_static_moduleが入っているかチェックします。

nginx -V

実行結果を見てみると・・

nginx version: nginx/1.1.19
TLS SNI support enabled
configure arguments: --prefix=/etc/nginx --conf-path=/etc/nginx/nginx.conf 
--error-log-path=/var/log/nginx/error.log --http-client-body-temp-path=/var/lib/nginx/body 
--http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-log-path=/var/log/nginx/access.log 
--http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi 
--lock-path=/var/lock/nginx.lock --pid-path=/var/run/nginx.pid --with-debug --with-http_addition_module 
--with-http_dav_module --with-http_geoip_module 
--with-http_gzip_static_module --with-http_image_filter_module --with-http_realip_module 
--with-http_stub_status_module --with-http_ssl_module --with-http_sub_module --with-http_xslt_module 
--with-ipv6 --with-sha1=/usr/include/openssl --with-md5=/usr/include/openssl --with-mail --with-mail_ssl_module 
--add-module=/build/buildd/nginx-1.1.19/debian/modules/nginx-auth-pam --add-module=/build/buildd/nginx-1.1.19/debian/modules/nginx-echo 
--add-module=/build/buildd/nginx-1.1.19/debian/modules/nginx-upstream-fair --add-module=/build/buildd/nginx-1.1.19/debian/modules/nginx-dav-ext-module

–with-http_gzip_static_moduleありました! よかったw

2. nginx.confファイル設定

nginx.confのgzip設定の部分を以下の様にしました。詳しくはこちら

##
# Gzip Settings
##

gzip on;
gzip_static on;
gzip_disable "msie6";
gzip_min_length 1000;
gzip_vary on;
gzip_proxied expired no-cache no-store private auth;
gzip_comp_level 9;
gzip_http_version 1.1;
gzip_types text/plain text/css image/png image/gif image/jpeg application/x-javascript text/xml application/xml application/xml+rss text/javascript;

設定を変更したら

sudo /etc/init.d/nginx restart

3. gzip生成シェルを作成

このモジュールは圧縮処理を行わないので事前にファイルをgzip圧縮しておかないといけなく、ファイルに変更があったときはその都度gzipしないといけません。
ここは変更があったファイルだけをgzipするように自動化したいところ・・・と思うのが当然で既にそれをしてくれるシェルを書いてくれている方がいらっしゃいました!
圧縮したいファイルの種類とトップディレクトリを指定すれば再帰的にサブディレクトリの圧縮するファイルを探してgzipしてくれます。
今回はこれをChefのレシピに追加してデプロイと同時にこれを実行するようにしました。

gzip_generator.sh.erb

#! /bin/bash

FILETYPES=( "*.html" "*.woff" "*.css" "*.jpg" "*.jpeg" "*.gif" "*.png" "*.js"  )
# specify a list of directories to check recursively
DIRECTORIES="<%= node['wp_install']['server_root'] %>"

for currentdir in $DIRECTORIES
do
   for i in "${FILETYPES[@]}"
   do
      find $currentdir -iname "$i" -exec bash -c 'PLAINFILE={};GZIPPEDFILE={}.gz; \
         if [ -e $GZIPPEDFILE ]; \
         then   if [ `stat --printf=%Y $PLAINFILE` -gt `stat --printf=%Y $GZIPPEDFILE` ]; \
                then    echo "$GZIPPEDFILE outdated, regenerating"; \
                        gzip -9 -f -c $PLAINFILE > $GZIPPEDFILE; \
                 fi; \
         else echo "$GZIPPEDFILE is missing, creating it"; \
              gzip -9 -c $PLAINFILE > $GZIPPEDFILE; \
         fi' \;
  done
done

Chefのレシピには以下を追加しました。詳しくはこちら

# script to keep gzipped file up to date
template "#{node['wp_install']['install_dir']}/gzip_generator.sh" do
  source "gzip_generator.sh.erb"
  owner node['wp_install']['user_name']
  group node['wp_install']['user_name']
  mode 00755
end

execute "create gzipped file" do
  command "./gzip_generator.sh"
  cwd node['wp_install']['install_dir']
end

効果検証

以下がGzipを有効にしていないときのデータ容量と読み込み時間をChromeのデベロッパーツールで測定したものです。

データ容量1.8MB, 読み込み時間3.56秒でした。

そしてhttp_gzip_static_moduleを有効にしたときは

データ容量961KB, 読み込み時間2.31秒になりました!

元のデータ量が少ないので一概には言えないですが、
http_gzip_static_moduleを有効にする前とした後では
データ容量:47%減少
読み込み時間:35%短縮
という結果になりました!

gzipでここまで読み込み速度が改善されるとは思っていませんでした。
GoogleさんのPagespeed Insightsからも「圧縮を有効にして!」と言われなくなりました!
まだまだ改善項目が多いので今後はNginxのproxy cacheなどにも挑戦したいと思います。

  • snoopyl3oy

    貴重な記事を書いていただきありがとうございます。

    全て読ませていただきましたが、質問が御座いまして、

    “今回はこれをChefのレシピに追加してデプロイと同時にこれを実行するようにしました。”

    とあるのですが、デプロイと同時に実行するには、
    具体的にはどのようなことをすればよいのでしょうか。

    ちなみに、レシピには追加して、一度chef-soloにてちゃんと実行することを確認しています。

    Chefに関して何分初心者ですのでご教授いただければと思います。

    • tactosh

      コメントありがとうございます!
      デプロイツール周りに関してあまり詳しくないのですが、今だとcapistranoやfabricあたりで、chefを実行するのが主流なんじゃないでしょうか。

      このブログのデプロイはまだ規模も小さいので、vagrant-awsを使って、
      $ vagrant provision
      をデプロイ代わりにしているだけなので、今後デプロイについてもしっかり考えないといけないです。
      http://tactosh.com/2013/12/vagrant-chef-wordpress-ec2-nginx/