CSS
HTTP
プロトコル
速度改善

【フロントエンドエンジニアだからこそ】プロトコルも理解して最適なコーディングしよう

前回レンダリングについて学んだことをまとめましたが、
今回はプロトコル(HTTP)について学んだことを超簡単にまとめてから
プロトコルに関連するパフォーマンス改善法を紹介しようと思います。

ネットワークプロトコルについて

プロトコル

コンピューター同士が通信をする際の手順や規約などの約束事...要は会話のための言語。
双方が理解できる同じプロトコル(言語)を使わないと通信(会話)は成立しないです。
バイリンガルでない限り日本語も同じじゃないと理解出来なくて伝わらないですよね。

プロトコルには沢山種類があって、物理的な部分からアプリケーション的な部分まで、物理層・インターネット層・トランスポート層・アプリケーション層と大きく分けて4段階あり...
みたいな説明が長々と続くわけですが、今回は要らないので省略。

HTTP

ブラウザと Webサーバの間で HTML などの Webページのコンテンツを送受信するためのプロトコル。(アプリケーション層)

そういえばたまに「HTTPプロトコル」なんて聞きますけど
HyperText Transfer Protocolの略なんで "プロトコル" 要らないです笑

【通信】

HTTPの通信は非常にシンプル!!
クライアント(ユーザ側)はサーバに対してHTTPリクエストを送信
↓ ↑ この間には TCPコネクションという みたいなものが出来ている
サーバはクライアントに対してHTTPレスポンスを返す

【バージョン】

HTTP にはバージョンが幾つかあり、現在支配的に利用されているのが HTTP/1.1 になります。
ですが最近は2015年に Google が SPDY のサポートを終了し、 HTTP/2 のサポートを開始すると発表してから、webパフォーマンスが向上しやすい HTTP/2 を取り入れるサイトが増えてきました。
参考:Google、「SPDY」終了と「HTTP/2」サポートを発表 - ITmedia NEWS

ということで今回は一番利用率の高い HTTP/1.1 と最新の HTTP/2 のパフォーマンスについて説明していきます。

HTTP/1.1とHTTP/2の違い

こちらも簡単に必要な部分しか書きませんので、詳細が気になる方は調べてみてください。

HTTP/1.1

  • 1つのTCPコネクション内に1対のリクエストとレスポンスしか処理できない
  • 同時に複数のリクエストを送ることは可能だが、その場合必ずリクエストされた順にレスポンスが返る
  • しかも殆どのモダンブラウザで TCPコネクションを同時に接続出来る数は 6つ
  • なので画像が100枚あったとしても一度に6枚分のリクエストしか送れない
    • 1枚分のレスポンスの受信が終わったら随時次のリクエストを送っていくため、常に6つ接続されていく

 2017-10-11 18.40.33.png

HTTP/2

  • 1つのTCPコネクション接続上にストリームと呼ばれる仮想的な通信路を作ることによって、複数のリクエスト/レスポンスを同時並行に処理できて、レスポンスを返すための処理に時間がかかるようなケースでも、その間に別のリクエスト/レスポンスを処理することが可能
  • なので画像が100枚あったとしたら一度に100枚分のリクエストが送れて、レスポンスも他の処理を待たずに返ってくる

 2017-10-11 17.01.55.png

【HTTP/2 を利用する場合の留意点】

現状 TLSプロトコルレイヤーなしでの HTTP/2 の利用を許可しているブラウザはない為、事実上TLSを利用する必要があります。
TLS(Transport Layer Security)プロトコルとは、一般的にSSL(Secure Sockets Layer)と呼ばれていて、

  • クライアントとサーバの認証機能
  • 通信データの暗号化
  • 通信データの改ざん検出

などの機能を提供し、セキュアな通信を可能にします。
URL のプロトコル部分が https:// だった場合、TLSが利用されています。

今見ているサイトはどのバージョン??

WEBサイトがHTTP/2に対応しているかどうかは、ブラウザの以下のプラグインを利用すると簡単に確認出来ます。

Chrome HTTP/2 and SPDY indicator - Chrome ウェブストア
Firefox HTTP/2 Indicator 3.0

プラグインを導入しサイトにアクセスするとアドレスバーの右側に稲妻マークが表示され色でバージョンが見分けられます。

バージョン
HTTP/2
SPDY
QUIC

体感しよう

HTTP vs HTTPS Test
このサイトでは、360個の画像ファイルを TSLなしの HTTP/1.1で読み込んだときと、
HTTP/2 で読み込んだ時のパフォーマンスの違いを試すことが出来ます。

HTTP/1.1 では読み込みが同時接続の制限によってブロックされ、全ての画像ファイルを読み込むのに時間がかかっているのが分かります。
一方、HTTP/2 では同時接続の制限がないため、多数の画像ファイルを高速で読み込むことが出来ます。

何でもかんでも変えればいいって話じゃない

HTTP/2 は HTTP/1.1 に比べ利点が多く見えるので
「全部 HTTP/2 化しちゃえばいいじゃん!!」ヽ(`▽´)/
と思われるかもしれません。
ですが、全てのサイトでただ導入すればサイトスピードが上がるのかと言われるとそうではないです。
効力が期待できないサイトというのもあります。
例えば

  • 既に HTTP/1.1 に適した処理を施しているサイト
    • HTTP/2 では無意味なテクニックを使っている場合、そのままのコードでは変化を感じられない
  • リクエスト数やリソースが元々少ないサイト
  • パケットロスが多いサイト
    • 多重化によって同時リクエストが可能となったが、TCPレベルでのブロッキングは解消されたわけではないので、パケットロスが多い環境では1本にした TCPコネクションが逆に影響されてしまう

などです。
これらのことから、HTTPS で多くのコンテンツを配信する ECサイトや同時アクセスが集中するサイトなどは特に HTTP/2の恩恵を受けることが出来ます。

HTTP/1.1 に合ったパフォーマンス改善法

HTTP/1.1では、リクエストできる数を増やすまたはリクエストする数を減らす事が高速化に繋がるテクニックになります。

リクエストを減らす方法

  • CSSスプライト
    • サイト内で使用するたくさんの画像(パーツ)をなるべく一枚画像にまとめて、サーバへのリクエスト回数を少なくする方法
    • CSS で調整する
      • img要素ではなく、背景画像として配置して幅を指定し、ボタンがひとつずつ表示されるように background-position でズラして調整する。
    • 更新が面倒(サイズが変わった時とか増えた時とか)
    • やりすぎると CSSが background-position で溢れ返って見づらくなる...??
  • 画像のインライン化
    • 画像などのバイナリファイルをBase64というテキストデータに変換してデータを HTMLの imgタグなどに埋め込む方法
      こんな感じになる→ <img src="data:image/png;base64,HFIKcsVBORwiHFIKcsVBORw">
    • データが数MB だと srcが途轍もなく長くなるため、htmlファイル自体のダウンロードに時間が掛かり不利になってしまう可能性がある
    • IE9以下はごめんなさい

リクエストできる数を増やす方法

  • ドメインシャーディング
    • 複数のドメインに分散させることによってドメイン数×6リクエスト分同時接続数を増やすことができる
    • ドメイン数が増えれば増えるほど、それぞれのドメインに対して名前解決しなければならないので、その時間が掛かりすぎると逆効果
    • もちろんコストと手間がかかる

どれも効果が出やすい技術ですが、やりすぎると逆効果になるのでご利用は計画的に
他にもリクエスト関連で出来ることを見つけたら随時更新しようと思います。

最後に

HTTP/2 では上記の技術は必要なくなります。
物によっては逆に遅くもなります。(ドメインシャーディングとか)
今回プロトコルを知って、何故効果がないのかがわかりました。

こういった技術は石ころのようにたくさんネットで公開されてますが、今動かしているサイトにこの技術は合っているのかを見分けて効果的で最適なコーディングをすることによって、パフォーマンス改善を目指していきたいなと思っています。