この多くのリクエストによる遅延を減少させるのもパフォーマンスに大きな効果があります。
ApacheやNginxなどの主要なWebサーバではKeepAliveという設定項目があります。これを有効化すると一度張ったHTTP接続によるTCPコネクションを再利用できるようになり、オーバーヘッドとなるTCPの3ウェイハンドシェイクの時間を省略することができます。ページ内のリクエスト数が多い場合には特に有効です。Webサーバの最大接続数などに注意しながら有効化を考えてみるとよいでしょう。
参考:HTTP接続のプーリングは可能か?
https://teratail.com/questions/14808
またドメインシェアリングという方法もあります。多くのブラウザでは同一ドメインに対する同時リクエスト数が6に制限されていますが、画像などの静的リソースを別のドメインに設置しそちらを読み込むことで、実質的にブラウザ側の同時リクエスト数を増やすことができます。
jQueryやCSSフレームワークのリクエストも、同ドメインに設置するよりも、それらを提供しているCDNサーバから読み込む方が、並列読み込みができるぶん読み込み完了までの時間が短くなる場合があります。小さい画像等が多い場合などは、画像配信用のサーバを用意するのが効果的です。
リクエスト数の削減
JavaScriptやCSS、画像などのリクエストを削減することも大きな効果があります。上記の通りブラウザの同時接続数には制限があるので、リクエストを減らすことでそれらが空くのを待つ時間を少なくすることができます。不要なファイルをリクエストしないのはもちろん、同じリソースでも工夫次第でそのリクエスト数を減らすことができます。
CSSスプライトは画像のリクエスト数を減らす代表的な例です。小さな画像を1つの画像にまとめてCSSの操作で個別に表示することで、複数の画像のリクエストを1つにすることができます。小さな矢印やアイコンなどは積極的にCSSスプライトにすべきです。またFont AwesomeなどのCSSによるアイコンセットを利用すればCSSで軽量にアイコンを利用でき、画像そのものの使用を減らすこともできます。
またCSSやJavaScriptファイルのリクエストも多くなりがちなリクエストのひとつです。小さなCSSやJavaScriptファイルは別ファイルにせず、HTMLにstyleタグやscriptタグで埋め込むことでリクエスト数を削減できます。
RequireJSやBrowserify、Webpackなどを用いてJavaScriptファイルを細かくモジュール化しつつも、最終的に1つのJavaScriptファイルにまとめて出力することで、大幅にリクエストを減らせます。ページ別にそれぞれ1つのファイルにまとめれば、不要なものを読み込む心配もありません。
通信量の削減
Webサーバからダウンロードするデータの容量を減らすことで、データのダウンロードにかかる時間を短縮することができます。またサーバやネットワークの通信帯域を節約することができるため、帯域が小さいモバイル端末には特に効果的です。
サーバ側でデータをgzip圧縮してデータの転送量を一律に減らすのが簡単です。Content-type
ごとに圧縮するものを選択することもできます。圧縮にWebサーバのCPUを利用するので、それとのバランスにだけ気をつければ通信量を大きく減らすことができます。
レスポンスヘッダのExpiresヘッダを適切に設定すると、リソースをブラウザ側にキャッシュさせることができます。ブラウザはリソースごとの最終更新日をリクエストヘッダに含めて送り、サーバ側で更新されていなければ304レスポンスが返り、ブラウザがキャッシュを利用する選択をします。これによりブラウザ内にキャッシュされている画像、CSS、JavaScript等を再利用することができます。
Apacheでブラウザキャッシュを設定する場合は、httpd.confでmod_expires.so
を読み込んだ上で、ドキュメントルートの.htaccessに以下のような内容を追記するのが簡単です。こちらもファイル形式ごとにキャッシュを保存する期間を設定することができます。
<ifModule mod_expires.c>
ExpiresActive On
ExpiresByType text/css "access plus 10 days"
ExpiresByType text/javascript "access plus 10 days"
ExpiresByType image/jpg "access plus 10 days"
ExpiresByType image/png "access plus 10 days"
</ifModule>
画像ファイルは特に容量が大きくなりがちなデータのひとつです。あらかじめ圧縮ツールを用いて不要なデータを省いて、透過が必要ないのであればPNGではなく圧縮率の高いJPGにするなどして容量を減らしておきましょう。大きな画像をブラウザ側で縮小して表示してしまっている場合は、前もって小さい画像を作成してからダウンロードさせるようにしましょう。
HTML、JavaScript、CSSを最小化するには最小化ツールを用いるとよいでしょう。上記のWebpackやSass等を使っても個別にファイルの最小化が実現できます。
HTTP/2
2015年5月に、HTTP/1.1よりもパフォーマンスを大きく向上させたHTTP/2の仕様が、RFC7540 として公開されました。
今までのHTTP/1.1では同時接続数が制限されているなどの問題点がありました。現在のWebでは1ページで何十ものリクエストとレスポンスがあることは珍しくないため、多くのサイトのパフォーマンスのボトルネックになっていました。パフォーマンスを追求する場合はCSSスプライトやJSの最小化、フロントエンドの配信に大きく気を使う必要があり、開発の流れや開発効率にまで影響を与えていました。
HTTP/2.0では1つのHTTPのコネクションで複数のストリームを流すことができます。このため同時接続数の制限がなくなり、レスポンスを待つことなくリクエストを送れるようになりました。
またHTTP/1.1ではリクエストヘッダが圧縮できず毎回数百byteの容量を毎回送信する必要がありましたが、HTTP/2ではHPACKという形式でヘッダをバイナリ形式で圧縮できるようになりました。これにより各リクエストの通信量が大きく減少します。
他にもリクエストを待たずにリソースをクライアントに送るサーバプッシュなど、パフォーマンスに関わるさまざまな機能が追加されています。
Apacheではバージョン2.4.17から実験的にですがデフォルトで組み込まれていて、オープンソース版Nginxでも1.9.5から採用されています。
参考:mod_http2 - Apache HTTP Server Version 2.4
https://httpd.apache.org/docs/2.4/mod/mod_http2.html
参考:Module ngx_http_v2_module
http://nginx.org/en/docs/http/ngx_http_v2_module.html
すでにGoogleやTwitterではHTTP/2が利用されています。HTTP2はHTTP/1.1との後方互換性を完全に保っていて、ChromeやFirefoxなどの主要なブラウザの多くはすでに最新版で対応していますので、今後はサーバ側の対応次第で少しずつ広まっていくでしょう。HTTPSが必須なのに注意し、パフォーマンスを求めるのであれば今の段階で試してみるのもよいかもしれません。
最後に
今回はWebサイトのパフォーマンスの改善策について、簡単に体系化して紹介しました。
実際にパフォーマンスを確認するには、ChromeやFirefoxなどのリクエストタイムラインが見られるブラウザで確認するか、WebdriverなどでHAR(HTTP ARchive)形式のデータを取得することで測定すると良いでしょう。リクエストタイムラインの縦のリクエスト数と横の読み込み時間をざっと見て、縦のリクエスト数をはじめに減らすのが王道です。
それぞれの方策がどういう意味を持つかを知って、現状に対する効果を考えながらボトルネックを適切に解消してパフォーマンスの向上を図りましょう。
teratail
https://teratail.com