メモログ

⛰ 塵が積もって山とならないメモのログ 👄

Navigation TimingとDom processing phase

Navigation Timingの仕様では、ナビゲーションや要素にアクセスするタイミングの情報を得ることができる。このNavigation Timingの情報を表示するには、ブラウザのデベロッパーツールなどのコンソールで、window.performance.timingを実行する。現在のサポートブラウザはCan I use… Support tables for HTML5, CSS3, etcの通り。

取得できる情報は下の画像のグラフのような値。最初の値であるnavigationStartは、ひとつ前のDocumentをunloadする作業を開始した直後に発生する(前のDocumentがなければfetchStartと同じになる)。そして、リダイレクトが必要なリダイレクトの時間、新しいDocumentの取得をし始めたらfetchStart、domainのlookup、サーバーとの接続、リクエスト、レスポンス、そしてDOMの処理へと進みます。このあたりは4.2 The PerformanceTiming interfaceに詳しく載っています。

domLoadingには、current document readinessが”loading”の状態になる直前の時間が入る(This attribute must return the time immediately before the user agent sets the current document readiness to “loading”)。current document readinessは、Documentオブジェクトの待ち受け状態で、Documentオブジェクトが新しく作成されると、そのDocumentのcurrent document readinessは「loading」の状態になる。つまり、domLoadingはDocumentオブジェクトが新しく作成されたタイミングで発生すると。

上の画像ではすべての処理が直列に行われるようなイメージですが、実際の動きを確認した限りでは、DocumentはresponseStartの直後に新しく作成するようで、responseEndより若干先に始まる(並列で処理される)。Firebugでperformance.timingを実行すると、下の画像のようなグラフィカルな感じになって見やすいのですが、「Dom Processing」の項目がresponseEndからdomCompleteの間までのグラフになっているので、若干語弊があるように見えなくもない(domLoadingは「Recieving」の途中で発生している)。でもクリティカルパスの可視化という意味では間違いではないかもしれない(responseEndが終わらない限りはDom processingが終わることはない)。そのあたりの意図は不明…

そしてdomLoadingの次はdomInteractive。これはcurrent document redinessが「interactive」の状態になる直前の時間で、interactiveは、HTML parserがストップしたらそのように設定される。つまり、HTML(DOM)のパースと、Javascriptの実行(スクリプトの評価とかイベントハンドラの登録とか)などが含まれる。scriptタグにdefer属性がある場合は「interactive」よりも後に実行される(DOMContentLoadedのイベント発生より前)。CSSについてはa style sheet that is blocking scripts と DOMContentLoadedで記載した通り、Javascriptがパーサーをブロックするかどうかで異なるけれど、たいていはinteractiveの前にavailable to scriptな状態になっているはず。

domInteractiveの後に、defer属性のついたscriptが処理されて、DOMContentLoadedのイベントが発生して、このイベントを待っている処理が実行される(DOMContentLoadedEventStart)。jQueryでready状態を待って処理を実行する場合は、DOMContentLoadedのイベントを待っているので、このタイミングで実行されることになる。

そしてDOMContentLoadedで実行された処理が終わるとDOMContentLoadedEventEndとなり、HTMLパースしたときに見つけた画像の読み込みなど、load event前に終わらないといけないものが残っていたら、終わるのを待って、current document redinessが「complete」になる。そして(on)loadイベントが発生する。(on)loadでイベントを待っている処理がある場合はそこから実行される。

という感じで、performance.timingでDom processingの流れをながめると、(1) domLoading -> (2) domInteractive -> (3) domContentLoadedEventStart -> (4) domContentLoadedEventEnd) -> (5) domComplete -> (6) load(EventStart/EventEnd) という観測地点があることが分かる。(1)から(2)までは、HTMLのパース(とJavascriptの読み込みと実行、あとたいていの場合CSSのロード)の処理の長さが推測できる。(2)から(3)は主にdeferになったscriptの実行時間、(3)から(4)はdomContentLoadedのイベントで発生した処理の時間(主にjQueryでreadyにしていた処理が入ると思われる)、(4)から(5)は、パース時に取得した画像の読み込みなど、そのほかload前に終わられる処理の時間などが推測される((5)から(6)はほぼ同時)。たぶん。