# とあるサイトの高速化についてフロントエンドでやったことまとめ。

- リンク: https://torounit.com/blog/%e3%81%a8%e3%81%82%e3%82%8b%e3%82%b5%e3%82%a4%e3%83%88%e3%81%ae%e9%ab%98%e9%80%9f%e5%8c%96%e3%81%ab%e3%81%a4%e3%81%84%e3%81%a6%e3%83%95%e3%83%ad%e3%83%b3%e3%83%88%e3%82%a8%e3%83%b3%e3%83%89%e3%81%a7/
- 公開日: 2014-11-27T09:30:11+09:00
- 作成者: Toro\_Unit

業務で携わっている案件なのですが、アクセス数の急増が見込まれるイベントがありまして。
準備期間も少なく、バックエンド側でできることがほぼないという状況でサイトを落とさ
ないようにがんばる！というお仕事でした。レガシーソースてんこ盛り。CSSプリプロセッサ
とか何それ状態。

そこで実施した対策のまとめです。サーバー・アプリケーション・サイトの構成によって、
効果の大小はありますが、比較的効果があったと思われるものをつらつらと。

## リクエストの削減とファイルサイズの最適化

まず一番最初に考えなければいけないのがリクエスト数です。すごいおおざっぱに言うと、
WEBサーバー（ApacheとかNginxとか）への負荷は、PV数×リクエスト数です。PVがそんなに
無くてもそのページのリクエストがめちゃくちゃ多いとそれだけでかなりの負荷になります。
リクエストを半分にできれば2倍の人数がさばけるってことに、すげーおおざっぱに言うとなり
ます。

ファイルサイズについてはそりゃ当然、軽ければ軽いほど良いわけで。

### Lazy Loadを導入して画像を遅延ロード

[Lazy Load](http://www.appelsiini.net/projects/lazyload)は、画像を遅延ロードする
プラグインです。画像がウィンドウの描画範囲に現れるまでロードしないというやつです。

    ```decode:true
    <img width="160" height="45" src="dummy.png" class="lazy" data-original="http://example.com/example.jpg" alt="" />

    <script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/jquery.lazyload/1.9.1/jquery.lazyload.min.js"></script>

    <script>
    $(function() {
        $("img.lazy").lazyload();
    });
    </script>
    ```

追記：当然、何でもかんでもLazy Loadにして良いかという話ではないです。HTMLの仕様的
にどうだとか、JSが無効だと見れなくなるだとか。個人的には、緊急回避の手段かなと思
ってます。

### CSS Spriteで画像を結合

メンテナンス性とのトレードオフな部分もあるんですが、それでも可能な限りCSS Sprite
にするとそれなりにリクエストを削れます。

また、同じような画像だと、トータルの画像サイズも下がる場合があります。

### CSSやJSも結合

当然、CSSやJSも結合できるものはとにかく結合。[grunt-contrib-cssmin](https://github.com/gruntjs/grunt-contrib-cssmin),
[grunt-contrib-uglify](https://github.com/gruntjs/grunt-contrib-uglify)とかを使う
と、それなりにメンテナンスせいを保ったまま、圧縮と結合ができるのでなかなか具合が
良いです。

### 画像の圧縮

画像の圧縮も当然ですが、[grunt-contrib-imagemin](https://github.com/gruntjs/grunt-contrib-imagemin)
や、 [grunt-image](https://github.com/1000ch/grunt-image)などを使って圧縮するのが
手軽です。

ただ、JPEGは元から圧縮されている関係上、この手の方法だとあまり効果が無い場合があり
ます。ファイルサイズが大きいものは、Photoshopで地道に目視で圧縮しました。品質を60%
くらいでもそんなに見た目変わらないので、やるなら思い切って削ると良いかなと。

## CSS / JS / 画像などの配信の最適化

ファイルサイズを削ったり、リクエストを削ったりってのは、CSSの書き方とか静的リソース
の作り方そのものの話でしたけど、これをいかにして高速に配信するかというのも結構大事
です。

### 静的リソース用サーバー立てる

おいおい、フロントエンドなのかそれは、と言われたらそりゃそうなんですけど。

静的リソース用サーバーとアプリケーションサーバーに求められるものは当然別です。画像
なんて一度アップロードしたら更新しないなんてことはざらにありますし。でもHTMLはそれなり
に更新がありますし、CMSとかが入ってるとまた大変な話。

サーバーからいじれたら、nginxをサーバーのフロントエンドに立てて、直接nginxから見
に行くようにするとかいろいろあるんですが、そういうわけにもいかなかったわけで。今回
は事情によりApache。

Amazon S3とか活用するのも有りだと思います。というかたぶんそっちの方がイマドキだし、
絶対早い。

### Keep-Aliveを有効に

普通に、HTTPでリクエストが飛ぶと、TCPハンドシェイクという動作が発生します。1リクエスト
ごとに、これが発生してしまうのですが、Keep-Aliveを設定しておくと、一定時間ハンド
シェイクを省略できるというやつです。

細かいこと言い出すときりがないので何ともいえないんですが、リクエスト数が多ければ
デフォルト値でもそれなりに有効な気がします。

    ```decode:true
    <ifModule mod_headers.c>
    Header set Connection keep-alive
    </ifModule>
    ```

サーバーによっては、.htaccessに上記の記述で有効になります。まぁ.htaccessでやる話
でもない気はしますけどね。

### Expiresヘッダの設定

Expireはファイルの有効期限です。この有効期限内であれば、ブラウザのキャッシュを利用
してくれます。これが未設定だと1週間くらいで失効してしまうのですが、これを適切に設定
することでリクエストをそれなりに削れます。

今回の案件は、7割か8割くらいはリピーターだったりで初見さんが少なかったのもあって、
これもそれなりに大きな効果があったのかなと思います。

最近では、.htaccessで設定できることが多いです。拡張子ごとに設定できます。以下のコード
だと、とりあえずCSSとJS、画像は1ヶ月キャッシュを有効にしてます。

    ```decode:true
    ExpiresActive On
    ExpiresByType image/gif "access plus 2592000 seconds"
    ExpiresByType image/png "access plus 2592000 seconds"
    ExpiresByType image/jpeg "access plus 2592000 seconds"
    ExpiresByType image/x-icon "access plus 2592000 seconds"
    ExpiresByType text/css "access plus 2592000 seconds"
    ExpiresByType application/x-javascript "access plus 2592000 seconds"
    ExpiresDefault "modification plus 1 week"
    ```

### CDNを活用する

jQueryだとかfontawesomeとか有名どころのライブラリは、CDNから呼びましょう。キャッシュ
があれば、当然それを使ってくれます。[cdnjs.com](http://cdnjs.com)なんかは有名です
ね。

また、一つのホスト（origin）への同時接続数はブラウザの標準設定で6つまでなので、その
ぶん他のリソースをロードできます。

## まとめ

フロントエンドの高速化といってもやることめちゃくちゃ多いし、幅広いなーというのが
印象でした。これ以外にもサーバーにサブドメインを複数割り当てて、一度にロードする
ファイル数を水増ししてみるとかいろいろやってみました。

結果としてとりあえず、Lazy Loadはかなり強力な手段だなと思いました。リクエストが発生
しなければそもそもサーバーに負荷はかからないので。細かい画像やバナーも多かったので、
リクエストがこれだけでかなりの数削減できました。

結局フロントエンドチューニングに銀の弾丸はやっぱり存在しないし、システム構成等でも
だいぶ変わってくる部分は大きいと思います。

レガシーなソースでもgruntとか入れるメリットはでかいなぁとも感じました。

やっぱり、基本的には「塵も積もれば山となる」的発想で立ち向かうしかないのかなと。
そもそも画像やCSSにしたって一つ一つのサイズはたいしたことないという事を考えると、
その「塵が積もって」サイトを遅くしてるんですからね。

## 参考

 * [身につけておきたいWebサイト高速化テクニック #2｜検証ツールとそもそもHTTPって何だ編 ｜ Developers.IO](http://dev.classmethod.jp/server-side/web-acceleration-tools-and-http/)
 * [スマホ向けWebアプリ開発で使えるフロントエンド高速化手法](http://www.slideshare.net/EijiKodama/build-insider)
 * [フロントエンドチューニングの箇条殴り書き ::ハブろぐ](http://havelog.ayumusato.com/develop/performance/e569-frontend_performance_memo.html)
