mod_rewriteでgzip圧縮に対応してみる

リライトとリライトがかぶってしまった

おまとめ三行

「戻りライト」と変換されてました
でもIEだからいいや別にぃ
Basic認証をかけているページでした

GoogleのPageSpeed Insightsというサービスを使うと、ウェブサイトの表示速度に関する改善点などを分析することができます。

これを見るといろんな改善案があるのですが、その中に「圧縮を有効にする」というのが出てくることがある。ざっくり言えば、サイトを見る時に読み込むcssやらjsファイルを圧縮して容量を軽減して、読み込み速度を上げましょう的なことです。

この圧縮を有効にする方法の一つに、mod_deflateってのがあります。.htaccessに必要な設定を書くと、サーバーがページ読み込み時にコンテンツの圧縮をしてくれるというもの。

そんな難しい設定じゃないし、便利な機能だとは思うんですが、ただこのmod_deflateは、レンタルサーバーによっては使えなかったりするみたいです。サーバーの負荷が上がってしまうからとか、そんな理由っぽい?

さくらインターネットのレンタルサーバーでは一応使えるようになってるみたいなのですが、僕がやったら上手く動いてくれませんでした。書き方を間違えていた可能性はあるけど。

そんなわけなので、今回は別のやり方、mod_rewriteを使って圧縮を有効にするやり方をやってみたいと思います。

今回の話とは全然関係ないんだけど、初めて「mod_rewrite」って単語を耳にした時、頭の中では「戻りライト」と変換されてました。しばらくはそう思ってました。だから「mod_rewriteを使ってアクセス制限すれば良いよ」みたいなことを言われた時、アクセスを禁止する人をどこかのページに戻してあげるのかなーとか、そんなことを思ってました。

戻りライト……ドラえもんの道具にありそうだ。ライトを当てると、光が当たった部分だけ、時間が巻き戻るの。タイムふろしきの懐中電灯版みたいなもんすかね。まあどーでもいいですね、うん。



圧縮ファイルを用意する

mod_deflateと違い、自動で圧縮してくれるわけではないので、まず圧縮ファイルを自分で用意する必要があります。

例えばstyle.cssとかfunctions.jsとかを有効にしたければ、それぞれ「style.css.gz」「functions.js.gz」という圧縮ファイルを用意する。

ファイルを圧縮するには、gzipコマンドを使います。

# gzip style.css
# gzip functions.js

これで、現在のファイル名にgzの拡張子がついた圧縮ファイルができます。サーバー上で直接コマンド叩いて作っても良いし、ローカル環境で作成してサーバーに上げても良い。ローカルでやる場合、Macならターミナルとか使ってgzipコマンドを打てば良いんですけど、Windowsはどうやるんだろ……たぶんデフォルトだと、gzipが使えないような気がするんで、まずgzipのダウンロードからしなきゃいけないかもです。でもすみません>< そこは未確認なんで、今回はパスで。

まあ、サーバーにアクセスできるなら、サーバー上でやっちゃった方が早いでしょう。

ちなみに、上記のようにgzipコマンドを打つだけだと、元のファイルがなくなってしまいます。今回は元のファイルも残しておきたいので、ローカルで作って上げるとかなら良いけど、サーバー上で直接作成する場合は、以下のようにコマンドを打った方が良いでしょう。何で元のファイルも残しておいた方が良いかは、後のお楽しみ。

# gzip -c style.css > style.css.gz
# gzip -c functions.js > functions.js.gz

これで元のファイルを残したまま、圧縮ファイルを作ることができます。



.htaccessの設定

続いて.htaccess。細かい説明は抜きにして、とりあえず書いてみましょ。

<IfModule mod_rewrite.c>
  RewriteEngine On

  RewriteCond %{HTTP:Accept-Encoding} gzip
  RewriteCond %{REQUEST_URI} (\.js|\.css)$
  RewriteCond %{REQUEST_FILENAME}\.gz -s
  RewriteRule .+ %{REQUEST_URI}.gz [L]

  <files *.js.gz>
      AddType "text/javascript;charset=utf-8" .gz
  </files>
  <files *.css.gz>
      AddType "text/css" .gz
  </files>
</IfModule>

gzip圧縮が使えるようであれば、jsとcssという拡張子のファイルを、元のファイルではなく「元のファイル名+.gz」のファイルを読み込むようにする、みたいなことをやっています。

gzip圧縮は、実は全てのブラウザで使えるわけではないようです。使えない場合もあるので、「RewriteCond %{HTTP:Accept-Encoding} gzip」で、まず使えるかどうかを判定しています。使えない場合は、元のファイルを読み込むようにしてやらないといけない。じゃないと、gzipが使えないブラウザでページを開いたとき、jsもcssも読み込んでくれなくなってしまう。元のファイルも残しておく必要があるのは、そういう理由です。



実際に確認

これで圧縮が有効になったはずなので、実際にブラウザでページを開いて確認してみると良いと思います。

確認する方法はいろいろあるんですが、手っ取り早いのは、PageSpeed Insightsで分析するか、ブラウザの検証機能を使って見てみることでしょうか。一度キャッシュを消して、ページを読み込んでみれば、圧縮されたファイルが読み込まれているか分かります。

例えば、あかつきのお宿のトップページを、Safariで見た場合。

字がちっちゃいかな……?

実際のファイルのサイズと、転送されたファイルのサイズが違いますね。圧縮が有効になっている証拠です。

Chromeで検証をすると、転送されたサイズしか見れないかもしれません。でも今回は自分で圧縮ファイルを用意してるので、サーバーを見れば元ファイルと圧縮ファイルのサイズが分かります。それと見比べて、圧縮ファイルの方が読み込まれているか確認できるでしょう。



さくらインターネットの場合

基本的にはこれでオッケーなんですが、さくらインターネットの場合、やはりこれだと上手く動いてくれないっぽいです。他のレンタルサーバーでも、同様の現象が起こるかもしれません。

詳しい原因がちょっとよく分からないんですけど、解決方法は、gzipが使えるかどうかの判定を行わないようにすれば、いけます。

<IfModule mod_rewrite.c>
  RewriteEngine On

  //コメントアウトする
  #RewriteCond %{HTTP:Accept-Encoding} gzip
  
  RewriteCond %{REQUEST_URI} (\.js|\.css)$
  RewriteCond %{REQUEST_FILENAME}\.gz -s
  RewriteRule .+ %{REQUEST_URI}.gz [L]

  <files *.js.gz>
      AddType "text/javascript;charset=utf-8" .gz
  </files>
  <files *.css.gz>
      AddType "text/css" .gz
  </files>
</IfModule>

これで圧縮が有効になります。

ただしこれだと、使えるかどうかの判定が入らないので、どんなブラウザで開いても、強制的に圧縮ファイルを読み込むようになってしまいます。なので、Acceps-Encodingの代わりにユーザーエージェントなどで判定して、圧縮を有効にした方が良いかもしれません。

例えばSafariやChromeで有効にしたい場合。

<IfModule mod_rewrite.c>
  RewriteEngine On

  //ユーザーエージェントによる判定
  RewriteCond %{HTTP_USER_AGENT} Safari
  
  RewriteCond %{REQUEST_URI} (\.js|\.css)$
  RewriteCond %{REQUEST_FILENAME}\.gz -s
  RewriteRule .+ %{REQUEST_URI}.gz [L]

  <files *.js.gz>
      AddType "text/javascript;charset=utf-8" .gz
  </files>
  <files *.css.gz>
      AddType "text/css" .gz
  </files>
</IfModule>

SafariもChromeもユーザーエージェントに「Safari」の文字が入っているので、これで圧縮を有効にできます。

こんな感じで、圧縮を有効にしたいブラウザだけ、有効にしていく……しかないのかな? ちょーっち面倒だよね。どのブラウザが対応してるのか、完璧に把握できてれば良いんだけど。

ちなみに僕は把握できていないので、とりあえず、グーグルアナリティクスを見ながら、それなりにアクセスがあってgzipが使えるブラウザだけ、有効になるようにしてみました。

IEはgzipに対応しているという噂なんですけど、僕がやったらダメでした。だからIEでは元ファイルの方が読み込まれています。どこか設定を間違えたのかな? でもIEだからいいや別にぃ( ̄△ ̄)





何でAccept-Encodingの判定が上手くいかないのか、すみませんがそこまでは原因が特定できませんでした。誰か知っている方がいれば教えてもらいたいです。ザ・他力本願。

そういえばこの前、PageSpeed Insightsで初めて100点を出すことができました。

Basic認証をかけているページでした。認証が通らないので、401エラーが返ってきていて、それで100点が出てました。そりゃ何のコンテンツも読み込まないんだから、改善すべきポイントなんてありゃせんわい。「ついにこのサイトにも100点のページがデターーー(゜∀゜)ーーー!!」って、一瞬でもテンションが上がった自分がダサすぎる┐(´ー)┌

まだコメントはいただけてないみたい……
もしかしたら何か関連しているかも?