ブラウザレンダリングを理解するため簡単にまとめてみた

初投稿です。よろしくお願いします(/･ω･)/

新卒入社してフロントエンドエンジニアとして働き始めて早半年。
最近は、自分の書いたコードが世の中にリリースされて嬉しさを噛み締めながら楽しく社会人生活を送っています。

# こんな本を読み始めました
[Webフロントエンド ハイパフォーマンス チューニング　-久保田 光則 (著)](https://www.amazon.co.jp/dp/4774189677/ref=cm_sw_r_tw_dp_x_.H2WzbZVB428T)


webパフォーマンスについて...要はサイトの **速度改善** について学べる本です。

冒頭に「ウェブパフォーマンスとは何か」が書かれてます。
>ウェブパフォーマンスを改善することは、ユーザが目的の達成の為に費やす時間やリソースを節約させることであり、その節約した分ユーザを豊かにしているわけです。

>ウェブページ遷移時の初期ロード時のパフォーマンスだけでなく
ウェブページ内でのインタラクション<span style="font-size: 80%;">(ユーザが起こした操作に対しての応答)</span>の描画のパフォーマンスが重要になってきます。

読み込み遅くてスクロールできないーとか、クリックしたのに反応遅いーとか
イラつきますよね。そうすると離れますよね。あるある。

でも折角作ったサイトが勿体無い。

じゃあ**フロントエンドエンジニアとして何が出来るのか?!**
って話がたくさん書いてあります。

# レンダリングの仕組みを知ろう
どういった技があるのかなーと読み進めると
最初にレンダリングの話がありました。

何故か。
> テクニックがなぜ有効かを正しく理解しなければ、実際の目の前のウェブページに正しく適用することは出来ないからです。

>開発者はその<span style="font-size: 80%;">(パフォーマンス測定の)</span>結果が意味するところは何なのかを理解し、その上でボトルネックを特定する必要があります。これらを読み解くには、ブラウザが何をしているのかを知らなくてはいけません。
そのためにも、ウェブ開発者はレンダリングの流れをおおまかにでも押さえておく必要があります。

なるほど。
私は作るのが好きでコーディングしてきただけの人間なので、全然レンダリングの流れ知りません。
なので、本を読みつつ、実際に検証っぽいのをしてみました。

## レンダリングの流れ
ブラウザのレンダリングには4つの工程があります。
最終的に描画されるまでをフレーム(Frame)と呼びます。
![20170921.jpg](https://qiita-image-store.s3.amazonaws.com/0/42808/d083ad74-4c85-8b8e-dfcb-1bf0bba9491f.jpeg)


* Loading
    * Download
    * Parse
* Scripting
* Rendering
    * CalculateStyle
    * Layout
* Painting
    * Paint
    * Rasterize
    * CompositeLayers

## 1. Loading
ここでは2つの処理が行われています。

### **Download**
ウェブページ(HTML)自身を含むリソース

* HTMLファイル
* CSSファイル
* JavaScriptファイル
* jpeg、png、gif、svg などの画像ファイル

をサーバからダウンロードする。

### **Parse**
ダウンロードしたリソースを**パース(構文分析)**してレンダリングエンジンの内部表現に変換する。

HTMLファイル → DOMツリー
CSSファイル → CSSOMツリー
## 2. Scripting
次に　JavaScriptのコードをJavaScriptエンジンに引き渡して実行させます。

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

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


## 3. Rendering
ここでも2つの処理が行われています。

### **CalculateStyle**
ドキュメントのDOMツリー内の全てのDOM要素に対して、どのようなCSSプロパティが当たるのかを計算する。
CSSルールのCSSセレクタがマッチするかを総当りで試行する。(総当りとか...がむしゃらな感じ 何それ可愛い)
そのあと個別のDOM要素に対して、どのようなCSSプロパティが適用されるかを判断する。

### **Layout**
CSSプロパティを算出した後、レンダリングエンジンはDOMツリー内全てのノードの視覚的なレイアウト情報の計算、**レイアウト**を行う。

レイアウト情報とは

* 要素の大きさ
* 要素のmargin
* 要素のpadding
* 要素の位置
* 要素のz軸の位置

のこと。

## 4. Painting
レイアウト情報の算出が終わると、最後のレンダリング結果の**描画**に移ります。

### **Paint**
DisplayListと呼ばれる内部の低レベルな2Dグラフィックエンジン向けの命令の列を生成する。
この辺でブラウザの実装毎にグラフィックエンジンの異なりが出てくる。

### **Rasterize**
生成された命令を用いて実際にピクセル(ビットマップ)へと描画する。
レイヤーごとに一枚一枚描画されていく。
レイヤーが生成されるのは要素に対して `position` や `transform` , `opacity`などのプロパティが適用されている時。

### **CompositeLayers**
最後に<span style="color: #ee6f0b">ピクセルにしたレイヤーを合成</span>して最終的なレンダリング結果を生成。
レイヤーは基本的にCPUによって合成されるが、transformCSSプロパティに3D変形関数をつけたり、いくつかの条件を満たすとGPUによって合成される。


レンダリング完成 (๑•̀ㅂ•́)و✧

## 実際に見てみた
Chromeのディベロッパーツールを使うとレンダリングの流れが表示される。
Performanceタブで ⌘Eを押して検証開始。
今回は1ページを表示させるのにどう動いたか知りたかったので、shift+⌘E。
<img width="719" alt=" 2017-09-21 15.55.52.png" src="https://qiita-image-store.s3.amazonaws.com/0/42808/3da711da-2757-5054-69e2-51f55e347f7a.png">
(赤枠で囲ったのが上で説明してたところの処理)

ファイルの読み込み順も見れる
<img width="1387" alt=" 2017-09-21 16.10.50.png" src="https://qiita-image-store.s3.amazonaws.com/0/42808/a88d21d2-2f11-85b3-4c99-c8f96c205711.png">
**HTML→CSS→JS→画像**の順に読み込まれてるのがよく分かる！

## 調べてみて
本にはもっと細かく書いてあるんですけど、まだまだプロトコルの話とかよく分かんなくて...

でも流れや構造が分かってよかった！
これから「私達が書いてるコードがこの流れにどう影響が出るのか」を理解していきたいです。
勉強することいっぱいだー(｡ŏ﹏ŏ)

あと、こういう長い記事書く時のコツとかも覚えたい。