Dev Study
← 1行のHTMLが画面に出るまで
レッスン 7 / 8·約 9 分·導線 1行のHTMLが画面に出るまで

DOMがピクセルになる — 描画は「DOM完成」を待たない

リクエストがアプリケーションに届くまで
  1. ブラウザURL入力今ここ
  2. DNS名前→IP
  3. ルータ経路選択
  4. ロードバランサ振り分け
  5. Nginx受け口
  6. アプリ処理
  7. DB保存

前回、バイト列は木になりました。今回はその木が箱になりピクセルになる継ぎ目を見ます。段の逐語と分担はブラウザ編へ。

まず結論

DOMは木の形をしたデータ構造で、できただけでは画面に何も出ません。ピクセルは Style・Layout・Paint・Raster・Draw が作ります。

その段が走るのは、イベントループが「レンダリング機会」で描画のタスクを実行したときです。仕様はこれを、DOMの完成にもレスポンスの完了にも結び付けていません。

? 読む前に予測

HTMLが最後まで届く前に、画面に何かが出ることはあるでしょうか。

当てることが目的ではありません。外した予測ほど記憶に残るので、直感で選んでください。

抽象原理

木ができても、画面には何も出ていない

前のレッスン『バイト列がDOMになる — 閉じ忘れても表示される理由』で、<h1>Hello</h1> から html・head・body を含む木ができるまでを見ました。

木ができた時点で、画面には何も出ていません。

DOMは入れ子のデータ構造で、そこに「何ピクセル目が何色か」は書かれていません。文字の大きさも行の折り返し位置もまだです。ピクセルを作るには次を順に決めます。

  1. Style — CSSを当てて、各要素の計算済みスタイルを作る
  2. Layout — 大きさと位置を決める
  3. Paint — 何をどう描くかの命令の並び(display list)を計算する
  4. Raster — その命令からピクセル(GPUテクスチャタイル)を作る
  5. Draw — 画面に出す

この5つは「DOMとピクセルの間にこれだけの段がある」ことを示す目印です。公式の段は12段あり、1段目は Animate、Parse という段も Composite という段もありません。 段の逐語と分担はブラウザ編『画面が出るまでの12段 — 5段モデルはどこから来たのか』と『誰がピクセルを作るのか — Layout・Paint・Raster の分担』で扱います。

押さえるのは1点です。Paint はピクセルを塗りません。 作るのは display list で、ピクセルを作るのは Raster です。

具体実物

では、その段はいつ走るのか

次の問いは「いつ走るのか」です。HTML仕様は描画の更新を "update the rendering" という手順として定義し、現行の仕様ではこれをレンダリングのタスクソースに積まれる1つのタスクとして書いています。

つまり描画は、イベントループの1周ごとに必ず挟まる固定のステップではありません。レンダリング機会があったときに描画のタスクが積まれ、それが実行されたときに段が走ります。機会の選び方について、仕様はこう書いています。

This specification does not mandate any particular model for selecting rendering opportunities.

「60fps」「16.7ミリ秒ごと」は、この文の直後に続く例示であって仕様の要求ではありません。この点はブラウザ編『イベントループ — タスクは集合、マイクロタスクは待ち行列』で確定済みです。

✓ ここまでの確認

「DOMツリーができた」は、画面について何を意味しますか。

抽象原理

仕様は描画を「DOM完成」に結び付けていない

多くの説明が「HTMLを読み終えてDOMができ、それから描画される」と書いています。しかし仕様に、描画の条件としてDOMの完成が挙げられている箇所はありません。 レスポンスの完了も条件ではありません。仕様が書いているのは次の3つです。

  1. パーサの進行は、典型的には1つのタスクである。 §8.1.7.1 のタスクの例示に、逐語でこう書かれています。

    Parsing The HTML parser tokenizing one or more bytes, and then processing any resulting tokens, is typically a task.

  2. 描画の更新は、レンダリングのタスクソースに積まれる別のタスクである。(前節の引用)

  3. 描画の条件は「レンダリング機会があること」であり、DOMの状態ではない。

この3点から、パースのタスクと描画のタスクは同じイベントループの上で順番を待つ対等な存在だと分かります。どちらが先に選ばれるかは、仕様が決めていません。

具体実物

対比: 書いた時点と、反映される時点

同じ構造はブラウザの外でも起きます。第39週『無停止で入れ替える — そして期末の切り分け』で扱う設定ファイルの反映がそれです。書いた時点と、外から見える状態が変わる時点の間には別の機構が1つ挟まっています。

✓ ここまでの確認

HTML仕様における「レンダリング機会(rendering opportunity)」の位置づけとして正しいものはどれですか。

⇄ 2つを見比べる
具体例 A

DOMと画面(描画のタスクが走った結果)

DOMを書き換えると木は即座に変わりますが、画面が変わるのは描画のタスクが実行されたときです。同期ループで書き換え続ける間、木は変わり続けますが画面は止まったままです。

同期ループ中の観測表
観測対象 ループ中 ループ終了後
DOMの状態 変わっている 変わっている
画面のピクセル 止まっている 更新される
具体例 B

設定ファイルと実際の挙動(第39週)

保存すると中身は即座に変わりますが、挙動が変わるのはリロードが処理されたときです。反映は入れ替えなので、途中では古い設定のまま応答するものが残ります。

リロード前後の観測表
観測対象 リロード前 リロードの途中
設定ファイル 変わっている 変わっている
実際の応答 古いまま 新旧が同居しうる

「書いた」と「反映された」がずれるのは、両者の間に何が挟まっているからでしょうか。

「書く操作」そのものが反映を起こすのかを、両方で考えてみてください。

抽象原理

図で見る: DOMから画面までの関門

DOMはピクセルの入力。間に「レンダリング機会」の関門がある
DOMデータ構造であって画面ではない
関門: レンダリング機会があると描画のタスクが積まれる
update the renderingレンダリングのタスクソースの1タスク
実行されると段が走る
Styleスタイル確定
Layout大きさと位置
Paintdisplay list
Rasterピクセルができる
Draw画面に出る
  • ・関門を通らない限り、DOMを書き換えても画面は変わらない
  • ・関門がいつ開くかを仕様は規定していない
  • ・段名は公式12段の一部。1段目は Animate で、Parse も Composite も存在しない

この章のまとめ

  • DOMはデータ構造。 木ができた時点で画面に何も出ていない。
  • Paint はピクセルを塗らない。 Paint は display list を計算し、ピクセルを作るのは Raster。公式の段は12段で1段目は Animate。Parse も Composite も段として存在しない。
  • 描画が走るのは、レンダリング機会に描画のタスクが実行されたとき。 "update the rendering" はレンダリングのタスクソースの1タスク。
  • 仕様は描画の条件をDOMの完成にもレスポンスの完了にも結び付けていない。 パースは典型的には1つのタスク、描画は別のタスク。
  • 「パースの途中で描画される」と明言した条文は無い。言えるのは「ありうる」まで。
  • 「書いた」と「反映された」の間には別の機構が挟まる。 画面が変わらないことは、書き込みが失敗した証拠にならない。

この先の学びにどう繋がるか

次のレッスン『JSが割り込む — <script> がパーサを止める理由』では、パースのタスクに <script> がどう割り込むかを見ます。段の逐語と分担、イベントループの処理モデルは、ブラウザ編『画面が出るまでの12段 — 5段モデルはどこから来たのか』『誰がピクセルを作るのか — Layout・Paint・Raster の分担』『イベントループ — タスクは集合、マイクロタスクは待ち行列』で扱います。既存のクイズでは「ブラウザ・エンジン」群と「フロントエンド」群のパフォーマンス問題が対応します。

自分の現場で確かめる

読んだだけでは身につきません。手元の環境で実際に見てみてください。

環境:

理解度チェック

読んだ直後は「分かった」と感じやすいものです。実際に解いて確かめてください。

問題 1 / 3正解: 0

「DOMが完成したので、その直後に画面が更新されます」という説明の問題点はどこですか。

用語集(5語)
DOM(ツリー)
パーサが組み立てた要素とテキストの入れ子構造。描画の入力であって、画面そのものではない。
rendering opportunity(レンダリング機会)
そのnavigableの内容をユーザーに提示できる状態。仕様は選び方を規定していない。描画はこの機会があるときだけ。
update the rendering
描画を更新する手順。現行のHTML仕様では、レンダリングのタスクソースに積まれる1タスクとして規定されている。
display list
Paint の段が計算する、描く内容の並び。ピクセルではなく、どうラスタライズするかの記述。
Raster
display list からピクセルを作る段。ソフトウェアで行う方式とGPUで行う方式がある。