ウェイブでエンジニアをしているKSです!
本記事では、Chrome DevTools を用いてレンダリングプロセスをご説明致します!
参照サイトとして、私が所属してるプロジェクトCoolmic(スマホ版のみ)を使用致します。
※ 2020/02/15 時点でのレンダリングの流れとなります。Coolmic では、現在、パフォーマンス改善を行っており、レンダリングの流れが変わる可能性がありますのでご了承ください。
web エンジニアの方は、自社サイトなどと照らし合わせながら本記事を読んでいただけると、イメージ湧きやすいかと思います!!
はじめに
Coolmic では、サイトパフォーマンス改善がミッションとなりました。 しかし、レンダリングの仕組みを断片的にしか把握していなかったため、適切な改善が行えない状況でした。 そこで、パフォーマンス改善前にレンダリングの仕組みを勉強し、社内勉強会を開催したため、その発表内容の一部を本記事にまとめました!
DevTools は回線を Fast 3G にしております!
注意事項
DevTools の使い方に関しては、本記事では説明致しません。
メルカリの記事が大変参考になりますので、ご参照ください。
また、パフォーマンス指標の FCP のタイミングまでのレンダリングプロセスについてまとめております。
パフォーマンス指標に関しても説明致しませんので、ご了承下さい。
レンダリングの仕組み
全体把握
◆ プロセス
大きく4つのプロセスがあります。
ただ、Painting の後に Scripting のプロセスが実行されることもあります。
以下の流れは一例と思っていただいて問題ありません。
◆ 全体イメージ図
1. Download HTML(Loading)
レンダリングに必要な HTML のデータをダウンロード。
※ 時系列をわかりやすくするため、あえて HTML のダウンロードのみ項目を分けました。
↓ 拡大
2. Loading
2-1. Parse
レンダリングエンジンが処理しやすいデータ構造体にデータ変換。
- HTMLファイル → DOM Tree
- CSSファイル → Style Rules(CSSOMツリー)
◆ DOM Tree
◆ Style Rules
◆ Devtools
2-2. Download Resources
リソース(Javascript, CSS, Image)のダウンロード。
◆ Devtools
3. Scripting
Javascript が実行されるタイミング( = レンダリングブロック )。
Evaluate Script のタイミングで Javascript が実行されている。
◆ Devtools
↓拡大
★レンダリングブロックについて
ここで、一度レンダリングプロセスから話を脱線致します。
先ほどの Loading フェーズで、Parse 完了までの時間が長いと感じた方も多いかと思います。
私自身もその一人です。
Q なぜ、FCP までの時間の大半を占めているのか🤔
A レンダリングブロックされているから😇
では、具体的に、何がレンダリングブロックに繋がっているというと、各リソース(HTML, CSS, Javascript)すべてが原因なり得ます。
◆ HTML, CSS の場合
レンダリング ツリーを構築するために DOM と CSSOM の両方が必須です。
そのため、HTML と CSS の両方がレンダリング ブロック リソース と言えます。
ファーストビューで不必要なデータを含めず、できるだけ早くレスポンスを返すことができるようにすることが重要です。
PageSpeed Insights でも重要なcssはインラインで配信することをおすすめされております。
◆ Javascript の場合
script タグを適切に使用しないと、大幅なレンダリングブロック発生原因となります。
重要なのは、属性の種類です。
サイト仕様に合わせて、async or defer どちらかを適切に使用することが重要です。
各属性のJavascriptダウンロード、実行タイミングが時系列でわかるこちらの記事も合わせてご参照いただけるとわかりやすいです。
属性 | Javascript実行タイミング |
---|---|
なし(デフォルト) | Parse をストップさせ、ダウンロード完了後、即座に実行される。 |
async | 非同期でダウンロード完了後、即座に実行される |
defer | 非同期でダウンロードし、Parse 完了を待つ Parse 後かつ DOMContentLoaded 前に実行される |
4. Rendering
4-1. CalculateStyle
DOM Tree と Style Rules を紐づけて、Render Tree 生成。
具体的には、どのスタイルがどの要素に適用されるのかをマッチングさせる。
◆ Render Tree
◆ Devtools
↓拡大
4-2. Layout
Render Tree を元に、要素の位置と大きさの情報を考慮した Layout Tree 生成。
以下の影響するプロパティーの変更があった場合に呼ばれる。
height, width, padding, margin, top, right, left, bottom, box-shadowなど
◆ Layout Tree
◆ Devtools
↓拡大
5. Painting
5-1. Paint
画面上への描写指示、Paint Records の作成。
並列で、Layer Tree も作成。
◆ Paint Records
Layout Tree を元に、要素の重なり(z-index)を考慮した Paint Records を生成。
◆ Layer Tree
Layout Treeを元に、Layer Tree(レイヤーツリー)を作成します。
Layer の分離は要素の変更の際の計算量を少なくする。
◆ Devtools
↓拡大
5-2. CompositeLayers
Main Thread に代わって Compositor Thread が実行。
まず、先程の作成した Paint Records を元に各レイヤーのピクセル単位で色を当て込んでいきます。
ラスタライズが完了したレイヤーは一つの合成レイヤーにまとめられ最終的にGPUに渡され画面に表示されます。
Painting の処理完了後、サイトが描画されます!
◆ Devtools
↓拡大
おわりに
レンダリングプロセスのどこに時間がかかっているか把握することができました🤗
最良なパフォーマンス改善を行うためには、仕組みの理解が大切だと改めて感じました。
また、パフォーマンス改善内容はサイトによって様々だと思いますので、目標設定に応じた適切な対応が必要です。
次回予告
Coolmic パフォーマンス改善してみた 〜 FP 1秒への道 〜