はじめに
- 『Webフロントエンドハイパフォーマンスチューニング』の第2章の自分用読書メモです
ブラウザを構成する主なコンポーネント
- レンダリングエンジン
- Javascriptエンジン
エンジンとは
外部にひとまとまりの特定の機能やサービスを提供するソフトウェアやシステムなどのこと
参照: https://e-words.jp/w/%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%B3.html
レンダリングエンジンとは
webページの描画、を提供するソフトウェア。
HTMLやCSSや画像ファイルなどの各種リソースを受け取って、それを画面に描画する役割を果たす。
リソースを受け取って描画する、という役割を果たすので、ブラウザ以外にも例えばHTMLメールの表示をサポートするために、レンダリングエンジンが組み込まれることもある。
代表例: Blink, WebKit
Javascriptエンジンとは
Javascriptの実行環境を提供するソフトウェア。
レンダリングエンジンとともに利用される場合には、DOMツリーやCSSOMツリーなどの内部のオブジェクトやAPIに対して、Javascriptからアクセスできるようにするバインディングが提供される。
Javascriptエンジンがあるからこそ、例えば
<script>
document.write('Hello World!')
</script>
のようなコードをHTMLファイルに記述してブラウザで表示しようとすると、ブラウザには「Hello World!」と表示される。
代表例: V8
ブラウザのレンダリングの流れ
大まかに分けると以下の四つのステップに分けられる。
Loading -> Scripting -> Rendering -> Painting
参照: https://www.seplus.jp/dokushuzemi/blog/2020/08/step_up2_specialist_css.html
Loading
リソースをダウンロードし、ダウンロードしたリソースをパースする。
ここでいうリソースとは
- HTMLファイル
- CSSファイル
- Javascriptファイル
- jpegなどの画像ファイル
のことを指す。リソース取得には様々なネットワークプロトコルを通じて取得する。ここでは本題から離れてしまうので詳細な説明は割愛するが、
- HTTP
- TLS
- TCP
- IP
- DNS
- UDP
あたりが理解できていたら良さそう。
さて、ダウンロードできたら、取得したリソースを元にDOMツリーを構築する。これがパース、という段階。
ブラウザはここで構築されたDOMツリーを元にして、Renderingの処理を実行する。
ここで構築されたDOMツリーはJavascriptからもアクセス可能。よく「DOM操作」と言われると思うが、上記の処理の流れから考えると「HTMLファイルを元に構築されたDOMツリーに対してJavascriptを実行することでDOMツリーの構造に変更を加える」と言い換えることができそう。
また、HTMLファイル内部には当然CSSファイルも埋め込まれている。レンダリングエンジンはここで埋め込まれているCSSファイルもCSSOM(DOMのCSS版みたいなもの)ツリーへと変換する。
これでLoadingの段階は終了。
Scripting
字句解析 -> 構文解析 -> コンパイル -> 実行
の流れで処理が行われていきます。
ざっくりと説明すると
Loadingの段階で取得したJavascriptのコードを
字句解析 -> 構文解析 -> コンパイル
で実行可能な形式に変換し、
実行
でJavascriptのコードを実行する。
JavascriptでDOMツリーを操作できるが、それによって後続のRenderingフェーズやPaintingフェーズを引き起こすことがある。また、外部のリソースを取得すると、Loadingフェーズを再度引き起こす。
パフォーマンスを考える際は、どのコードが実行されたらどのフェーズから処理が始まるかを意識する必要がある。
Rendering
Renderingのフェーズでは
- スタイルの計算
- レイアウト
を行う。
スタイルの計算
Loadingフェーズで構築したCSSOMツリーから、どのDOM要素にどのCSSプロパティが適用されるかを判断する。
レイアウト
スタイルの計算でどのDOM要素にどのCSSプロパティが適用されるかが判明した。
ここではそれらの情報から、Paintingフェーズで使用するレイアウトツリーというものを作成する。
Painting
レイアウトツリーを元に
- ペイント
- ラスタライズ
- レイヤーの合成
を経て、レンダリング結果を生成し、webページとして閲覧できるようになる。
ペイント
描画するための命令の生成を行う。
ラスタライズ
命令を元にレイヤーという単位で一枚一枚描画する。
なぜレイヤーという単位で描画するのかというと、z軸の上限関係を考慮するため。
レイヤーの合成
複数作成されたレイヤーを合成する。
レイヤーの合成にはCPUとGPUが使用される。
2DならCPU、3DならGPUの方が処理が向いている。
雑記
- フロントエンドを扱うエンジニアなら知っておいて損はなさそう
- 特にLoadingの解説はわかりやすかった(プロトコルの話も含め)
- とあるReactプロジェクトをChromeの検証ツールの「Performance」タブを開くと予想通りScriptingに最も時間をかけていた(画像添付)
- 前半のインプット量多かったため、後半(Painting)になってくると疲れてしまったので後日読もう
参考
詳細を学びたい方はこちら
もっとちゃんと学びたいのであれば、書籍を買うか、以下の記事を読むのがオススメです。
ハンズオンで学びたい方はこちら
少し趣向が違うのですが、Loadingフェーズを理解するのに大変参考になりました。
伸び悩んでいる3年目Webエンジニアのための、Python Webアプリケーション自作入門