1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

WebフロントエンドAdvent Calendar 2024

Day 23

ブラウザがHTMLを受け取ってからDOMツリーを構築するまで

Last updated at Posted at 2024-12-24

はじめに

ブラウザはアドレスバーに入力されたURLをもとにHTTPリクエストを作成し、Webサーバーへ送ります。

Webサーバーから返されるHTTPレスポンスにはステータスラインやレスポンスヘッダ、レスポンスボディが含まれています。

レスポンスボディにはHTMLや画像などが含まれますが、ブラウザはこのHTTPレスポンスからHTMLを受け取り、解析・表示を行っています。

本記事では、HTMLがどのように解析され、DOMツリーが構築されていくのかの概要についてみていきます。

アドレスバーにURLを入力してからHTMLを受け取るまで

アドレスバーにURLを入力してからHTMLを受け取るまでの流れを簡単にまとめてみます。

URLの解析

まず、アドレスバーに入力されたURLを解析し、スキーム(HTTP/HTTPSやFTP、FILEなど)、ホスト(ドメイン名)、ポート番号、パス、クエリパラメータなどの構成要素に分割します。

DNSによる名前解決

ドメイン名からリクエスト先のIPアドレスを取得します(名前解決)。

まずはhostsファイルやDNSキャッシュ1を確認し、対象のレコードがないかを確認します1

キャッシュがなければブラウザはOSのDNSリゾルバに問い合わせを行います。
OSのDNSリゾルバは(ISPなどの)ローカルDNSサーバやルートDNSサーバ、トップレベルドメインサーバや権威サーバへと順次問い合わせていき、IPアドレスを取得します。

TCP接続の確立

IPアドレスが判明したら、ブラウザはそのサーバとTCP接続を確立します(3ウェイハンドシェイク)。

TLS(HTTPSの場合)

HTTPSを使用している場合には、ブラウザとサーバーの間でTLSハンドシェイクが行われ、通信が暗号化されます。

HTTPリクエストの送信

ブラウザはHTTPリクエストを作成してサーバーに送信します。
HTTPリクエストにはリソースのパス、HTTPメソッド(GETなど)、ヘッダー情報などが含まれます。

サーバーからHTTPレスポンスが返される

サーバーはHTTPレスポンスをブラウザに送ります。
HTTPレスポンスにはステータスラインやレスポンスヘッダ、レスポンスボディ(HTML、CSS、JavaScriptなどのコンテンツを含む)が含まれます。

大まかには上記の流れで、アドレスバーにURLを入力してからHTMLを受け取ります。

レンダリングエンジン

レンダリングエンジンとは、ブラウザ内にあるHTMLの描画のためのコンポーネントです。

HTMLはレンダリングエンジンのHTMLパーサーによって解析されます。
この解析結果をもとに、レンダリングエンジンはDOMツリーを構築します。

レンダリングエンジンにはいくつか種類があり、ブラウザによって採用されているものが異なります。
Google Chrome やMicrosoft Edge2ではBlinkというレンダリングエンジンが採用されています。
また、Safari ではWebKit、FireFox ではGecko が採用されています。

ちなみに、ブラウザのシェア率は以下のサイトで確認できます。

HTMLの解析

レンダリングエンジンはまずHTMLパーサーによって、HTML文字列に対して字句解析・構文解析を行い、その結果をもとにDOMツリーを構築します。

字句解析

レンダリングエンジンのHTMLパーサーは、HTMLを構成する文字列をトークンと呼ばれる、「意味を持つ最小の単位」へと分割します。
<!DOCTYPE html>などが意味を持つ最小の単位となります。
他にも、開始タグを表すトークンや終了タグを表すトークン、文字トークンやコメントトークン、空要素タグトークンなどへとそれぞれ分割されていきます。

構文解析

字句解析によってトークン化された結果をもとに、構文木と呼ばれる木構造を構築していきます。
トークン化された要素の親子関係、入れ子構造などを階層構造に反映していきます。

DOMツリーの構築

構文木をもとにして、DOMツリーを作成していきます。
構文木をもとにパーサーがDOMツリーに1つずつ要素を追加していきます。

ここで、<script>タグが見つかった場合には、パーサーの処理を一時的に停止してJavaScriptを実行します。
パーサーの処理を一時的に停止するのは、JavaScriptによってDOMツリーの構造に変更がはいる可能性があるためです。
パーサーの処理が停止することはパフォーマンス上もよくないため、実行タイミングをDOMツリー構築後に遅らせるdefer属性を使用することでパーサーの一時停止を回避する方法をとることもできます。
また、外部スクリプトの場合にはダウンロード中もパーサーが停止してしまいます。
そのような場合には、async属性を<script>タグに付与することで、ダウンロード中はパーサーを停止させず、ダウンロードが完了し次第パーサーを一時停止してJavaScriptを実行させることもできます。

また、JavaScriptからはこの時点までで構築されているDOMツリーにアクセスすることも可能です。
getElementByIdなどで要素を取得する際に、<script>タグよりも前に記述されている要素しか取得できないのは、<script>タグの後ろに記述されている要素がまだDOMツリーへ追加されていないためです。

以上の流れでDOMツリーが構築されていきます。

  1. ブラウザのDNSキャッシュ、OSのDNSキャッシュやルーターのDNSキャッシュを確認します。 2

  2. かつてはEdgeHTMLが採用されていましたが、Blinkへ移行しています。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?