3分でわかった気になれるブラウザレンダリングの仕組み【Webフロントエンドハイパフォーマンスチューニング第2章読書メモ】

# はじめに
- 『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エンジンがあるからこそ、例えば

```html
<script>
  document.write('Hello World!')
</script>
```

のようなコードをHTMLファイルに記述してブラウザで表示しようとすると、ブラウザには「Hello World!」と表示される。

代表例: V8

# ブラウザのレンダリングの流れ
大まかに分けると以下の四つのステップに分けられる。
> Loading -> Scripting -> Rendering -> Painting

参考にできる画像があったので、添付する。
![rendering_flow.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462620/3316994f-9404-f939-50bb-b3d2a9396c1f.png)

参照: 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)になってくると疲れてしまったので後日読もう


![スクリーンショット 2021-10-04 20.10.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462620/a53c7cc7-a952-2dec-85a3-ce305b9bdc1b.png)



# 参考
[『Webフロントエンドハイパフォーマンスチューニング』](https://gihyo.jp/book/2017/978-4-7741-8967-3)

# 詳細を学びたい方はこちら
もっとちゃんと学びたいのであれば、書籍を買うか、以下の記事を読むのがオススメです。

- https://zenn.dev/ak/articles/c28fa3a9ba7edb
- https://qiita.com/sasakiki/items/91dcc8b50d7a61ce98bc

# ハンズオンで学びたい方はこちら
少し趣向が違うのですが、Loadingフェーズを理解するのに大変参考になりました。
[伸び悩んでいる3年目Webエンジニアのための、Python Webアプリケーション自作入門](https://zenn.dev/bigen1925/books/introduction-to-web-application-with-python)