ブラウザレンダリング入門

こんにちわ！gasheeeeです。
Qiita初投稿させていただきます！！

今年の春に新卒フロントエンジニアとして入社させていただき、
Web未経験ですがサービスに携わらせて頂いております。

今回の記事は、トレーナーさんからおすすめされた技術本である
『[*Webフロントエンド ハイパフォーマンス チューニング*　著 久保田 光則](https://www.amazon.co.jp/Web%E3%83%95%E3%83%AD%E3%83%B3%E3%83%88%E3%82%A8%E3%83%B3%E3%83%89-%E3%83%8F%E3%82%A4%E3%83%91%E3%83%95%E3%82%A9%E3%83%BC%E3%83%9E%E3%83%B3%E3%82%B9-%E3%83%81%E3%83%A5%E3%83%BC%E3%83%8B%E3%83%B3%E3%82%B0-%E4%B9%85%E4%BF%9D%E7%94%B0-%E5%85%89%E5%89%87-ebook/dp/B0728K5JZV?pf_rd_p=58c92908-f2b1-4cbf-98d2-8911a92c77a0&pd_rd_wg=RuVqN&pf_rd_r=FRS35D0T5Z0QBKQMSWDF&ref_=pd_gw_cr_simh&pd_rd_w=TZJav&pd_rd_r=94783cf9-c1f8-4c4f-9b8f-8c0ab5845405)』の『***ブラウザレンダリングの仕組み***』についての記事を書いていこうと思います。

##レンダリングの仕組みがなぜ重要なのか
レンダリングの仕組みを説明する前に、そもそもなぜレンダリングの仕組みを学習しなければいけないのかについて解説が書かれていました。
>テクニック（チューニングテクニック）がなぜ有効かを正しく理解できなければ、実際の目の前のウェブページに正しく適応することはできないからです。
パフォーマンスを測定してどこにボトルネックがあるかを特定した後に、そこを解消するために開発者は最適化を施します。しかし、レンダリングにどのようなフェーズがあるのかを知っておかなければ、なぜそこが問題になっているのか、解消するためにどうすればいいのかが、あやふやになってしまいます。

いくらパフォーマンスを上げる方法を知っていたとしても、なんで今このテクニックを使うのかを理解できないと問題点があやふやになるということですね。

##レンダリングの工程
ブラウザレンダリングの工程は大きく分けて**4つの工程（Loading、Scripting、Rendering、Painting）**があり、この一連の流れを**フレーム**と言います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165820/ee2f1fee-db77-506c-b010-0ec97dba60d4.png)

##各工程で行われていること
それぞれのフェーズでどのような処理が行われているかを説明していきます。
###1.Loading
このフェーズでは以下の**２つの処理（Download、Parse）**を行います。
####Download
ここでは、ウェブページ(HTML)自身を含む以下のリソースをサーバーからダウンロードします。

- **HTMLファイル**
- **CSSファイル**
- **JavaScriptファイル**
- **画像ファイル（PNG、JPEG、GIF、 etc..）**


####Parse
ここの工程では、ダウンロードしたリソースを**構文分析（パース）**してレンダリングエンジンの内部表現に変換します。
HTMLコンテンツはDOMツリーに、CSSはCSSOMツリーに変換され、それ以外のリソースも、レンダリングエンジンに応じた内部表現変換されます。

- HTMLコンテンツ  --変換--> DOMツリー
- CSS --変換--> CSSOMツリー

###2.Scripting
ここでは、JavaScriptのコードをJavaScriptエンジンに引き渡して実行させます。

〜Scriptingの流れ〜
JavaScriptのコード → **字句解析** → トークン列 → **構文解析** →
→ 抽象構文木 → **コンパイル** → 実行可能コード → **実行**

コードのトークン列をパースして抽象構文木を作成し、コンパイルすると、実行可能になります。
Javascriptの実行は、最初にJSファイルを読み込んだ時以外では、DOMイベントが発火しイベントリスナが起動する時にも起きます。

###3.Rendering
この工程では以下の**２つの処理（Calculate Style、Layout）**が行われます。

####Calculate Style
ここでは、ドキュメントにあるDOMツリーの中の**全DOM要素**に対して、**どんなCSSプロパティが当たるのか計算**を行います。
CSSOMツリーの中をすべて参照して、CSSルールのセレクタのマッチング処理が、このときに行われます。全DOM要素に対して、CSSルールのセレクタがマッチするかを**総当り**で行います。
それが終わった後、**CSSルールの詳細度を算出**し、個別のDOM要素に対して、どのCSSプロパティが当てられるかを判断しています。

####Layout
ここでは、全てのDOM要素に適用するCSSプロパティを算出した後、レンダリングエンジンはDOMツリー内の全ノードの視覚的な**レイアウト計算**を行います。

レイアウト情報は以下のものを示しています。
1. **要素の大きさ**
2. **要素のmargin**
3. **要素のpadding**
4. **要素の位置**
5. **要素のz軸の位置**

###4.Painting
ここでは、**３つの処理(Paint、Rasterize、Composite Layers)**を行い、レンダリング結果の描画を行います。

#### Paint
ここでは、RenderTreeを元に、**DisplayList**と呼ばれる内部の低レベルなグラフィックエンジン向けの命令の列を生成します。
また、各ブラウザの実装毎にグラフィックエンジンが異なっています。

#### Rasterize
ここでは、生成された命令を用いて実際に**ピクセル(ビットマップ)**へと描画します。
このときに、レイヤーごとに一枚一枚描画されます。
このレイヤーが生成されるのは、ある要素が以下の条件にある場合です。

- 要素```position``` : ```absolute```または```fixed```の場合
- 要素```transform``` : ```translate3d(0px,0px,0px)```のようなGPUで描画、合成されるCSSプロパティの場合
- 要素に```opacity```CSSプロパティが適用されて、透過して背後のコンテンツが表示される必要がある場合

#### Composite Layers
ここでは、ピクセルにしたレイヤーを合成して最終的なレンダリング結果を生成します。
レイヤーは基本的に**CPU**によって合成されますが、3D変形関数をつけるなどのいくつかの条件を満たすと**GPU**によって合成される場合があります。

## 終わりに
今回はブラウザレンダリングについて、自分も学ばせてもらいながら記事を書かせていただきました。
まだまだ分かんないことが山積み。。。
ですがっ！！
新しい技術本を読むたび、自分の理解できる技術が増えていくことをとても実感しています！
これからもどんどん新しい知識を取り入れて、アウトプットしていこうと思いましたっ！！

記事を読んで頂いた方々、最後まで拙い内容でですがお読みいただきありがとうございました。