ブラウザの心臓部を止めろ:スクリプトによるパースブロックの深層と、限界を超えた非同期制御
フロントエンドエンジニアなら誰もが一度は「なぜか画面の描画がもたつく」「インタラクションが遅延する」という壁にぶつかったことがあるはずだ。Lighthouseのスコアを睨みつけ、なんとなく `async` や `defer` を貼り付けてみたものの、ブラウザのメインスレッドで何が起きているのかを正確に説明できる者は少ない。
HTMLパーサーがなぜ突然足を止めるのか。そして、V8などのJavaScriptエンジンとレンダリングエンジンがメモリ上でどうせめぎ合っているのか。今回は、ブラウザの内部挙動を愛してやまないあなたに向けて、スクリプトによるパースブロックの正体と、その呪縛から逃れるための高度なアーキテクチャを紐解いていこう。
—
1. パースブロックの正体:なぜ `` はHTMLパーサーを絶望させるのか
ブラウザがネットワーク経由でHTMLのバイトストリームを受け取った瞬間から、壮大なパインプラインが動き出す。Decoderが文字コードを解釈し、Tokenizerがトークンを切り出し、最終的に DOM(Document Object Model)ツリー が構築されていく。
ここで運命の分かれ道となるのが、同期的な `
この要素は上のスクリプトが読み終わるまで絶対に存在しない
なぜ、ブラウザはこの単純な行でHTMLのパースを完全に停止(Block)させるのだろうか? 答えはシンプルで、そして残酷だ。「JavaScriptからDOMが変更される可能性があるから」である。
// スクリプト内でこんなコードが書かれていたらどうなる?
document.write('
');
もし、パーサーが先読みしてDOMツリーを先に構築してしまっていたら、`document.write` やツリー構造を根底から書き換えるスクリプトに出くわしたとき、それまでの苦労がすべて水の泡になる。メモリ上で構築されたツリーの整合性が破壊され、再構築コスト(レイアウト・ペイントのバースト)は計り知れないものになる。
そのため、ブラウザエンジンは安全側に倒す。同期的な `

コメント