こんにちは!
株式会社Hajimariでエンジニアインターンをしている溝口と申します!
今回はブラウザレンダリングの仕組みについて書いていきます!
この内容にしようと思ったのは最近、ブラウザ描画周りの知識不足が原因で開発に詰まったことがきっかけです。
これまでずっと理解が曖昧な状態で開発していて、調べることを後回しにしていました。
今回の失敗を機に、曖昧だった部分をしっかり理解しておこうと思い、ブラウザレンダリングについて記事を書くことにしました!
レンダリングの流れ
早速ですがブラウザレンダリングについて、説明をしていきます!
この記事では、レンダリングとはブラウザがデータを受け取ってから、表示するまでの一連の動作のことを指します。 ※加えて今回、DOMツリー構築までのHTML Parseなどについては記事が長くなるため省略します。
以下がレンダリングの全体像です。
- DOM構築
- CSSOM tree構築
- JavaScriptの実行
- レンダーツリー構築
- レイアウト
- ペインティング
自分は初めて全体像を見た時何一つ理解できてませんでした。
1つずつ見ていきましょう。
DOMツリー構築
ブラウザを表示するために最初に行われるのがDOMツリー構築です。
※HTMLはサーバから送られた状態では表示形式に変換されていないため、DOMツリー構築までにいくつかの工程があるのですが、今回はDOMツリー構築までの流れの説明は省きます。
DOMツリーとは
DOMツリーとはこのようなHTMLを表示するためのデータ構造です。
そもそもDOMとは何でしょうか?
Document Object Modelの略で、HTMLやXMLをJavascriptなどで外部操作できるインタフェースを定義したものです。
つまりDOMというのはあくまで実体の無いインターフェイス定義のことで、DOMを元にしてDOMツリーというオブジェクトが作られていくんですね。
DOMに基づいて、各ノードがツリー状に作られていきます。
親要素がbody、子要素がdiv4つ、孫がp2つずつの場合、このような形になりますね。
この時に階層が深ければ深いほど読み込みに時間がかかります。
つまり、マークアップをシンプルに書く方が読み込み速度が上がります。
CSSOMツリーの構築
DOMツリーの構築中にCSSファイルやCSSの記述が合った場合、CSSOMツリーというものが構築されます。
DOMツリーと同じツリー状のデータ構造になっています。
CSSOMツリーに書かれた内容が、スタイルとして適用されていきます。
このCSSOMツリーが作られる際にCSSの読み込みを行うのですが、CSSの読み込みのルールが少し複雑になっているので、簡単に説明します。
CSSの読み込みのルールを理解するためには、まず詳細度という概念を理解する必要があります。
※詳細度を重みと表現しているドキュメントもありますが基本的な意味は同じです。
詳細度というのはセレクタの詳細度と言えます。
CSSは、同じ要素に対して複数のセレクタを使っている場合、詳細度の高いセレクタが優先されます。
詳細度が高いとはどういうことか、具体例を見ていきましょう。
こちらをご覧ください。
下のh1要素に対して以下のCSSが書かれています。h1要素の文字は何色になるでしょうか?
<div> <h1 class="title"> ... </div>
div h1 { color: green; } .title { color: white; } h1 { color: red; } h1 { color: blue; }
正解はdiv h1
です。文字はgreenのため緑になります。
h1
よりも.title
よりも、div h1
の方がセレクタが詳細になっています。そのため、このセレクタが優先されます。
クラスセレクタと要素セレクタではクラスセレクタの方が優先度は高いのですが、詳細度のある方が優先されるためdiv h1
が優先されます。
この詳細度が詳しいセレクタが優先される概念はカスケードと言われます。
ちなみに、CSSは「Cascading Style Sheets」の略です。(自分はCSSのCがカスケードを意味することを初めて知りました。笑)
カスケードは英語で「滝のように落とす」という意味で、CSSが詳細度の低いものから詳細度の高いものを読み込んでいく特徴を表しています。
詳細度の他にもCSSには継承という概念が読み込みの優先度にも関わっているのですが、今回は割愛します。 継承についてはこちら。 https://developer.mozilla.org/ja/docs/Learn/CSS/Building_blocks/Cascade_and_inheritance#%E7%B6%99%E6%89%BF%E3%82%92%E7%90%86%E8%A7%A3%E3%81%99%E3%82%8B
JavaScriptの実行
DOMツリーの構築中にJSファイルやJSの記述が合った場合、その場でJSが実行されます。
この時JSの実行が終わるまでDOMツリーの構築はJSの処理が終了するまで中断されます。
つまりCSSと同じようにJSの処理が重ければその分画面表示が遅くなるということですね。
レンダーツリー構築
DOMツリーとCSSOMツリーが作成されると、DOMツリーとCSSOMツリーを1つのツリーにまとめます。
そうして作られるのがレンダーツリーです。
レンダーツリーは画面に表示されるノードのみが作成されます。display: none
の付いてるHTML要素やheadタグなどは含まれないという点に注意です。
レイアウト
レンダーツリーが作成されたら、viewport内に各ノードのサイズや位置を計算して決めていきます。
position: absolute; width: 33%; などの計算を行います。
ペイント
レイアウトが済んだレンダーツリーをピクセルに変換して、ブラウザ画面に結果を描画します。
まとめ
以上がブラウザ画面の描画の流れになります。
- ①DOM構築
- ②CSSOM tree構築(DOM構築に含まれる)
- ③JavaScriptの実行(DOM構築に含まれる)
- ④レンダーツリー構築
- ⑤レイアウト
- ⑥ペインティング
普段何気なく使っている裏側の処理を知ることの大切さを今回感じました。サイトのパフォーマンス改善をするためにはブラウザの裏側の処理を理解することは必須です。
それに今回記事を書く中で、HTMLやCSSの書き方が表示速度に直接影響することを知りました。どう動いているのか?どう表示されているのか?と言った仕組みへの理解は良いコードを書くために欠かせない要素だと思います。
今回調べたのはブラウザ描画の流れの中の一部分についてなので、更に詳しく調べて全体像をまとめた記事を後日出そうと思います。
拙い文章にも関わらず、ご精読ありがとうございました!
株式会社Hajimariでは、Laravelをメイン言語として自社開発・受託開発を行なっており、
一緒に開発を行なっていただけるエンジニア募集しています!
長野拠点の立ち上げメンバーも大募集しています!
興味のある方は以下の記事をぜひご覧ください!
みなさまとお会いできるのを心からお待ちしております!
www.wantedly.com www.wantedly.com www.wantedly.com www.wantedly.com