オブジェクトモデルの構築

公開日: 2014 年 3 月 31 日

ブラウザがページをレンダリングするには、DOM ツリーと CSSOM ツリーを構築する必要があります。そのため、HTML と CSS の両方をできるだけ早くブラウザに配信する必要があります。

  • バイト → 文字 → トークン → ノード → オブジェクトモデル。
  • HTML マークアップはドキュメント オブジェクト モデル(DOM)に変換され、CSS マークアップは CSS オブジェクト モデル(CSSOM)に変換されます。
  • DOM と CSSOM は独立したデータ構造です。
  • Chrome DevTools の [パフォーマンス] パネルでは、DOM と CSSOM の作成と処理のコストをキャプチャして検査できます。

ドキュメント オブジェクト モデル(DOM)

<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <link href="style.css" rel="stylesheet" />
    <title>Critical Path</title>
  </head>
  <body>
    <p>Hello <span>web performance</span> students!</p>
    <div><img src="awesome-photo.jpg" /></div>
  </body>
</html>

試してみる

最もシンプルなケースから始めましょう。テキストと 1 つの画像を含む単純な HTML ページです。ブラウザはこのページをどのように処理しますか?

DOM の作成プロセス

  1. 変換: ブラウザは、ディスクまたはネットワークから HTML の未加工バイトを読み取り、ファイルの指定されたエンコード(UTF-8 など)に基づいて個々の文字に変換します。
  2. トークン化: ブラウザは、文字列を W3C HTML5 標準で指定された個別のトークン(<html><body> など)と、角かっこ内の他の文字列に変換します。各トークンには特別な意味と独自のルールがあります。
  3. レキシング: 生成されたトークンは「オブジェクト」に変換され、そのプロパティとルールが定義されます。
  4. DOM の作成: 最後に、HTML マークアップは異なるタグ間の関係を定義するため(一部のタグは他のタグ内に含まれます)、作成されたオブジェクトはツリー データ構造でリンクされ、元のマークアップで定義された親子関係もキャプチャされます。ドキュメントの表現全体が構築されるまで、HTML オブジェクトは body オブジェクトの親であり、bodyparagraph オブジェクトの親です。

DOM ツリー

このプロセス全体の最終的な出力は、シンプルなページのドキュメント オブジェクト モデル(DOM)です。ブラウザは、ページの以降のすべての処理にこの DOM を使用します。

ブラウザは HTML マークアップを処理するたびに、バイトを文字に変換する、トークンを識別する、トークンをノードに変換する、DOM ツリーを作成する、という前述のすべてのステップを実行します。このプロセス全体には、特に処理する HTML の量が多い場合は時間がかかることがあります。

DevTools での DOM の作成のトレース

Chrome DevTools を開いてページの読み込み中にタイムラインを記録すると、このステップの実行に実際にかかった時間を確認できます。上の例では、HTML のチャンクを DOM ツリーに変換するのに約 5 ミリ秒かかりました。ページが大きい場合は、この処理にかなり時間がかかることがあります。スムーズなアニメーションを作成するときに、ブラウザが大量の HTML を処理する必要がある場合、これがボトルネックになる可能性があります。

DOM ツリーはドキュメント マークアップのプロパティと関係をキャプチャしますが、レンダリングされた要素の外観はわかりません。これは CSSOM の責任です。

CSS オブジェクト モデル(CSSOM)

ブラウザが基本ページの DOM を構築しているときに、外部 CSS スタイルシート(style.css)を参照するドキュメントの <head><link> 要素が見つかりました。ページのレンダリングにこのリソースが必要になることを予測して、このリソースのリクエストをすぐにディスパッチします。このリクエストから、次のコンテンツが返されます。

body {
  font-size: 16px;
}

p {
  font-weight: bold;
}

span {
  color: red;
}

p span {
  display: none;
}

img {
  float: right;
}

スタイルを HTML マークアップ内で直接宣言することもできますが、CSS を HTML から独立させることで、コンテンツとデザインを別個の問題として扱うことができます。デザイナーは CSS に取り組むことができ、デベロッパーは HTML とその他の問題に集中できます。

HTML と同様に、受信した CSS ルールをブラウザが理解して処理できるものに変換する必要があります。したがって、HTML のプロセスを繰り返しますが、HTML ではなく CSS に対して行います。

CSSOM の構築手順

CSS バイトは文字、トークン、ノードに変換され、最終的に「CSS オブジェクト モデル」(CSSOM)と呼ばれるツリー構造にリンクされます。

CSSOM ツリー

CSSOM がツリー構造になっているのはなぜですか?ページ上のオブジェクトの最終的なスタイルセットを計算する際、ブラウザはまず、そのノードに適用される最も一般的なルールから開始します(たとえば、body 要素の子要素の場合は、すべての body スタイルが適用されます)。次に、より具体的なルールを適用して、計算されたスタイルを再帰的に絞り込みます。つまり、ルールは「下り(ダウン)カスケード」されます。

具体的に説明するために、前述の CSSOM ツリーについて考えてみましょう。body 要素内に配置された <span> タグに含まれるテキストは、フォントサイズが 16 ピクセルで、赤色のテキストになります。font-size ディレクティブは body から span にカスケードされます。ただし、span が段落(p)タグの子要素である場合、その内容は表示されません。

また、前述のツリーは完全な CSSOM ツリーではなく、スタイルシートでオーバーライドすることにしたスタイルのみを示しています。すべてのブラウザには、デフォルトのスタイルセット(「ユーザー エージェント スタイル」とも呼ばれます)が用意されています。これは、独自のスタイルを指定していない場合に表示されます。Google のスタイルは、これらのデフォルトをオーバーライドします。

CSS の処理にかかる時間を調べるには、DevTools でタイムラインを記録し、[スタイルの再計算] イベントを探します。DOM 解析とは異なり、タイムラインには個別の [CSS を解析] エントリは表示されず、代わりに解析と CSSOM ツリーの構築、およびこの 1 つのイベントで計算されたスタイルの再帰計算がキャプチャされます。

DevTools での CSSOM の作成のトレース

単純なスタイルシートの処理時間は約 0.6 ミリ秒で、ページ上の 8 つの要素に影響します。これはそれほど多くありませんが、無料ではありません。しかし、8 つの要素はどこから来たのか。CSSOM と DOM は独立したデータ構造です。ブラウザが重要な手順を非表示にしていることが判明しました。次に、DOM と CSSOM をリンクするレンダリング ツリーについて説明します。

フィードバック