ブラウザの仕組み&レンダリングの流れについて備忘録

「Webフロントエンド ハイパフォーマンスチューニング」読んだ。仕組みも知らずに闇雲にチューニングしたって効果的な速度改善なんかできるわけないやろってことでブラウザの仕組みとレンダリングの流れについてから解説が始まって、これがなかなか面白かったので要点をまとめとく。


ブラウザの仕組み

ブラウザはレンダリングエンジンとJavaScriptエンジンによってできている。
ブラウザによって使ってるエンジンが違うので表示内容も違う。誰もが一度はMS製ブラウザに憎しみを抱いてしまうのもこのせい。

レンダリングエンジン

リソース(HTML,Image,CSS,JavaScript)を読み取って画面に描画する機能。
日本で2019/1時点でのレンダリングエンジンのシェア率はこんな感じ。
レンダリングエンジン シェア率 ブラウザ
Blink 44.24% Chrome,Opera,Android Browserなど
WebKit 33.84% Safari
Chakra 9.45% IE
Gecko 6.01% Mozilla FireFox
EdgeHTML 4.16% Edge

BlinkはWebKitをフォークして作られているので、現状レンダリングエンジンはWebKit系が大半のシェアを占めてる状態。ちなみにMicroSoftもブラウザの独自開発やめてEdgeもChromeと同じエンジン使っていくよーって発表が最近出て、Blink一強状態を懸念する声も多いみたい。

JavaScriptエンジン

主にJavaScriptをコンパイルするための機能。
こっちはレンダリングエンジンと違ってブラウザごとにほぼバラバラ。Chromeが採用している「V8」はNode.jsでも利用されている。



レンダリングの流れ

URL叩く → Loading → Scripting → Rendering → Painting(画面表示)

1. Loading

1. Download
  ネットワークプロトコルを通じてリソースを取得する
  1. URLの名前解決(DNS → UDP/TCP → IP)
  2. TCP → TLS(https://~の場合のみ)
    TCP接続 + TLS接続を確立するためにパケットを3往復する必要がある(3ウェイハンドシェイク、TLSハンドシェイク)
    例:最速パケット到達時間が20ms = 接続までに120msかかる 
  3. HTTPリクエスト → HTTPレスポンス受け取り

2. Parse
  リソースをパース(構文解析)する
  1. HTMLをDOMツリーへ変換
  2. CSSをCSSOMツリーに変換

2. Scripting

1. Scripting
  1. JavascriptコードをレンダリングエンジンからJavascriptエンジンへ引き渡す
  2. JSコードをトークン列に変換
  3. トークン列を抽象構文木(コンパイル可能な形)に変換
  4. コンパイル
    Javascriptエンジンによってコンパイル方法が異なる
    主要な方法:JITコンパイラ - CPUが直接解釈できる機械語に変換する方法。実行時コンパイラ(対義語:AOTコンパイラ - 事前コンパイラ。Java,Cなどで使用)
    あれ、JITコンパイラとインタプリタ言語の違いとは???ってなったので以下wikiの内容。
JITコンパイラ - ソフトウェアの実行時にコードのコンパイルを行い実行速度の向上を図るコンパイラのこと 
インタプリタ - プログラミング言語で書かれたソースコードないし中間表現を逐次解釈しながら実行するプログラムのこと 
  5. 実行

3. Rendering

1. Calculate Style
  スタイルの計算
  1. DOMツリーの中のどのDOM要素にどのCSSがマッチングするか総当たりで計算する
    マッチング処理は右から左に解釈されて行われる
    例:.wrap > .contents > .main_btn
      1. 全てのDOM要素から.main_btnに該当するものを探す
      2. その中から.contentsに内包されているものを探す
      3. さらにその中から.wrapに内包されているものを探す
      =ハンパねぇ数計算してるよ!ってことですね。
  2. CSSの詳細度(優先順位)を計算して適用するCSSを決定する
    どんな風に計算されるかは以下サイトで確認できる
    Specificity Calculator

2. Layout
  レイアウト情報(要素の大きさ、余白、位置等)を計算する

4. Painting

レンタリング結果をユーザの見える形に描画する
1. Paint
  グラフィックエンジン向けの命令を生成
2. Rasterise
  Paintで生成された命令を使用してレイヤー(z軸ごとに生成される)単位で描画
3. Composite Layers
  1. CPUによりレイヤーを合成
    ※translate3dなどの3D情報が含まれる場合はGPUにより合成されることが多い
  2. レンダリング結果を生成