メモログ

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

a style sheet that is blocking scripts と DOMContentLoaded

DOMContentLoaded and stylesheets · molily(via DOMContentLoaded - Mozilla event reference | MDN)にて、head内のスタイルシートとJavascriptの配置の違いで、DOMContentLoadedイベントが発生するタイミングが変わるという内容が掲載されています。スタイルシートのあとにJavascriptが入っていると、DOMContentLoadedはスタイルシートをロードしたあとに発生して、スタイルシートのあとにJavascriptがないと、スタイルシートのロードを待たずにDOMContentLoadedが発生する。

これはParsingの仕様によると、pending parsing-blocking scriptの実行前に、Documentが has no style sheet that is blocking scriptsの状態になるまで、event loopをspinさせるからということになるみたい。

If the parser’s Document has a style sheet that is blocking scripts or the script’s “ready to be parser-executed” flag is not set: spin the event loop until the parser’s Document has no style sheet that is blocking scripts and the script’s “ready to be parser-executed” flag is set.

つまり、pending parsing-blocking script(HTMLパーサーがinsertしたscriptタグのうち、deferやasync属性がついていないもの)が実行前に、style sheet that is blocking scripts(HTMLパーサーが追加したスタイルシートのうち、ロードされていないもの(style sheet ready flag is not yet set))がある場合、ロードされるまでevent loopをまわす。スタイルシートがロードされ、style sheet readyの状態になると、event loopの「update the rendering」のステップでscriptでの利用が可能な状態になり、他にロード待ちがなければscriptの実行に移ると。こうすることで、スタイルシートで指定しているフォントの色なんかの値を、scriptが適切に受け取ることができると。

DOMContentLoadedのイベントは、8.2.6 The endに記載によれば、HTMLのパースが一通り完了して、defer属性がついたscriptなどを処理したあとに発生する。ので、スタイルシートの後にscriptがある場合、scriptがパーサーをブロックしつつスタイルシートのロードを待った上で実行されるため、DOMContentLoadedはスタイルシートがロードされるまで待つことになる。一方、スタイルシートの後にscriptがない場合は、パーサーをブロックしてロードを待つことがないため、ロードが完了していなくても、HTMLパースが完了してDOMContentLoadedのイベントが発生する。と、いうことになる。みたい。

ただ、DOMContentLoaded and stylesheets · molilyTestcase #2で試した感じでは、Operaはscriptの実行前にスタイルシートのロードを待たない雰囲気。そのためDOMContentLoadedの実行がロードより早く、getComputedStyleで取得したフォントの色の値にスタイルシートで設定した色が反映できていない(他のブラウザはheadの部分でパーサーがブロックされるのでコンテンツが表示されるまでに時間がかかる)。

Operaの動作の差異を気にしないとしても、scriptの実行時(ダウンロード時ではない)にスタイルシートがavailableな状態になっていないと、実行はブロックされた状態になるので、スタイルシートのロードをできるだけ先にして、javascriptはできるだけ後にする、というのが基本的には良いかもしれない。

scriptで現在のスタイルの値をまったく参照しないみたいな、スタイルシートとscriptを独立できるのであれば、scriptを先に読み込むというのもありかもしれません(その方がロードによるブロックは発生しない)。ただ、Safari(6)とChrome(24)では、結局スタイルシートがロードし終わるまでコンテンツが表示されなかったですが…(Firefoxは表示される)