実際のところ「ブラウザを立ち上げてページが表示されるまで」には何が起きるのか
問題のツイート
解釈
今回は「ChromeのURL欄に入力してからページが表示されるまで」をやります。ブラウザの起動云々はWeb系の話じゃないと信じてます。
1. HTTPリクエストが飛ぶ
HTTP2のヘッダ圧縮技術に全て書いてありました。
実際のリクエストヘッダ
:authority: www.google.co.jp
accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
accept-encoding: gzip, deflate, br
accept-language: ja,en-US;q=0.9,en;q=0.8
cache-control: max-age=0
cookie: 🤫
upgrade-insecure-requests: 1
user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.81 Safari/537.36
x-client-data: CJW2yQEIpbbJAQjBtskBCKmdygEI2J3KAQjancoBCKijygEIh6fKAQ==
今回はリクエストメソッドがGETなのでヘッダのみですが、POSTやPUTの場合はデータがリクエストボディで送られます。詳しくはHTTPメソッド(CRUD)についてまとめたなどを参照してください。
余談ですが、何年か前に【パズル1】ほとんどのエンジニアには解けるが、下位10%のダメなエンジニアにだけ解けないパズル?で遊んだのを思い出しました。楽しくHTTPメソッドについて学べるパズルなので解いていない人はぜひ解いてみてください。
実際のレスポンスヘッダ
HTTP/1.1 200
status: 200
date: Tue, 11 Sep 2018 09:36:30 GMT
expires: -1
cache-control: private, max-age=0
content-type: text/html; charset=UTF-8
strict-transport-security: max-age=3600
content-encoding: br
server: gws
x-xss-protection: 1; mode=block
x-frame-options: SAMEORIGIN
set-cookie: 1P_JAR=2018-09-11-09; expires=Thu, 11-Oct-2018 09:36:30 GMT; path=/; domain=.google.co.jp
alt-svc: quic=":443"; ma=2592000; v="44,43,39,35"
レスポンスヘッダは上みたいな感じで、このヘッダと一緒に届くレスポンスボディが<!doctype html>〜〜
というhtmlドキュメントです。
もっと低レイヤーについてはOSI参照モデルまとめが分かりやすいです。
DNS?何ですかそれは。
ドメイン名のしくみ | 何も知らない人用
DNSパケットフォーマットと、DNSパケットの作り方 (1/2) | じゃあ実際DNSプロトコルってどんなデータを送ってるの?という人用
Cloudflareが1.1.1.1で超高性能DNS始めたし、いっちょ俺のパソコンもDNS over HTTPSしてみる | 俺は検閲には屈しねぇ!という人用
DNSプロトコルってよく分かりませんしHTTPSで名前解決できたら楽でいいですよね。
2. レンダリングエンジンが描画を行う
レスポンスボディで返ってきたhtmlドキュメントを元にブラウザに搭載されているレンダリングエンジンが画面を描画します。
Chromeの場合はBlinkというエンジンが搭載されています。
(image from How Blink works by Kentaro Hara)
で、このBlinkで行われているレンダリングプロセスが下図です。
(image from How Blink works by Kentaro Hara)
htmlドキュメントを解釈してDOMを構築し、styleを当てはめてレイアウトしてから描画です。あとはLife of a Pixel 2018を見てください。マジで分かりやすいのでオススメです。これを見た後じゃあ自分で書き直そうという気にはなれませんね。
でも「どうしてもお前が書いた解説が読みたいんだ!!!」という人の為に書きます。正直これ以降の部分は質が微妙です。プロのあなたの助けを求めています。コメント・編集リクエストお待ちしています。
DOMとは
Document Object Modelの略です。chromiumのDOMのページに実装などの情報がまとまっています。
「いやDocument Object Modelって何やねん」となると思うのですが、端的にいうと木です。tree。
データ構造の選択次第で天国と地獄の差 (3/3) | tree構造とは
DOMはChromeで「⌘+⌥+i」を押すと出現する検証モードの「element」の項目に並んでいるアイツです。キーボードに⌘キーや⌥キーが無い場合はこちらへどうぞ。
(例)google.co.jpのDOM
DOCUMENT (always the root)
└─HTML
├─HEAD
│ └─...
└─BODY
├─DIV
│ └─...
├─SCRIPT
└─SCRIPT
それぞれのnodeの実装
(image from core/dom/README.md by きらきら☆はやとたん)
親はfirstChildとlastChildの情報しか持ってないそうです。連結リストってヤツですね。
レンダリングエンジンはHTML文章を解析し、上記のようなDOMツリーを構築します。
Style
レンダリングエンジンはCSSを解析してCSS Object Modelツリーを構築します。
元のCSS
body { font-size: 16px }
p { font-weight: bold }
span { color: red }
p span { display: none }
img { float: right }
⬇️CSSOM
(image from オブジェクト モデルの構築 by Ilya Grigorik)
DOMとCSSOMを組み合わせるとRender Treeが完成します。
(image from レンダリング ツリーの構築、レイアウト、ペイント by Ilya Grigorik)
ちなみにこのCSSOMはJavascriptにexpose(日本語訳求む)されているのでwindow.getComputedStyle() で要素のスタイルを取得する事ができます。
Layout
レンダリングツリーを元に、個々の要素がウィンドウ内のどこに配置されるかを決めていきます。
(image from CSS Box Model Module Level 3)
上の画像みたいなCSS Box Modelを使って、親から子へと再帰的に、つまり子は親のcontent内にレイアウトされていきます。CSSでは親要素との相対的な位置関係で記述されていますが、レイアウト処理の出力段階では画面上の絶対的な位置になります。
(image from Life of a Pixel 2018)
(image from Life of a Pixel 2018)
中のコンテンツがスペースをオーバーしてもOKで、その時の選択肢は全て表示する「visible」、オーバーした部分を表示しない「hidden」、そしてスクロールできるようにする「scroll」の3つです。
SCROLLING IN BLINK | スクロールの仕組みについて。position: stickyって初めて知ったけどめっちゃ便利じゃないですか?もっと早く知りたかった……
後LayoutNGなる新しいレイアウトシステムが開発中らしい。
Paint
表示されるべき要素とそのスタイルが計算できたので、最後にそれぞれの要素を実際のピクセルに落とし込んでいきます。
(image from Life of a Pixel 2018)
DOMツリーとは関係なく、描画リストの順番で描画されていきます。CSSのz-indexを設定する事で順番を明示的に指定できます。
(image from Life of a Pixel 2018)
また、backgroundやfloatなどの要素によってどれが上に来るのかが変わるので、背後の要素が部分的に前に出て来ることもあるらしいです。
この描画工程が終わると画面にページが表示されます。
Compositor thread
ブラウザのレンダリング処理は全てmainスレッドという一つのスレッドで行われます。スレッドが一つしか無いというのは、javascriptなどで何か重たい処理を実行してしまいスレッドを埋めてしまった場合にスクロールなど基本的な操作すらおぼつかなくなってしまう危険があるということです。
そこで、スクロールやアニメーション、ズームなど「レイヤーの移動・スケールの変更」で対処できるものに関しては、レンダリングが終わった後に別スレッドへと移動させ、スムーズな操作を可能にしようというのが「Compositor Thread Architecture」です。
(image from Life of a Pixel 2018)
終
プロの方々のコメントや編集リクエストをお待ちしています。よろしくお願いします。
この記事よりもLife of a Pixel 2018を読みましょう。ブラウザのレンダリングについて学ぶなら最高にオススメのスライドです。