ドキュメントの解析とDOMContentLoadedトリガーのタイミング

はじめにHTMLドキュメントが完全にロードされて解析された後、DOMContentLoadedイベントがトリガーされることは誰もが知っていますが、HTMLのコンテンツはドキュメントの解析にどのように影響しますか?解析中にスクリプトタグまたはリンクタグが検出された場合、解析は影響を受けますか?さまざまな状況の例を通して、HTML5仕様と一緒に分析してみましょう。

DOMContentLoadedトリガー定義

HTMLドキュメントが完全に読み込まれ、解析されると、DOMContentLoadedイベントがトリガーされます。通常、ドキュメントへの外部スタイルシートと画像の読み込みはイベントのトリガーに影響しませんが、後で説明する特殊なケースがあります。

スクリプトタグが検出されると、ドキュメントの解析が停止してスクリプトが実行されます。これは、スクリプトによって一部のdocument.write操作などのDOMが変更される可能性があるためですが、async属性が設定されたスクリプトタグはイベントのトリガーに影響しません。

以下は、いくつかのシナリオでのDOMCOntentLoadedのトリガータイミングの詳細な分析です。

スクリプトタグ

ドキュメントの解析動作は、スクリプトタグの属性設定によって異なります。

HTML5仕様のscripttag属性に関する部分:  html.spec.whatwg.org/multipage/s…

主な非同期プロパティと遅延プロパティは次のとおりです。

  1. async:スクリプトが使用可能になると、スクリプトはすぐに実行され、リソースを要求するプロセスで解析がブロックされません。リソース要求が完了した後、この時点でドキュメントが解析されていない場合、解析はブロックされます。スクリプトリクエストがドキュメントの解析時間よりも長くかかる場合にのみ、影響はありません
  2. defer:スクリプトの実行を延期して、ドキュメントの解析がブロックされないようにします。つまり、スクリプトがネットワークリクエストから完了した場合でも、ドキュメントの解析が完了した後でのみ、スクリプトはすぐには実行されません。

それらの属性値はすべてブール値であり、src属性が存在する場合にのみ有効です。

仕様に示されている解析タイムチャートは非常に明確です。赤い線はスクリプトスクリプトの解析を表し、緑はhtmlの解析を表し、青はネットワークリソース要求を表します。

没设置属性的时候,script 标签在请求和执行的时候都会阻塞文档解析。defer 和 async 属性设置后,请求阶段不会影响解析,但是 async 的标签会立即执行,影响解析。后面 type="module" 的情况跟上面相同。

总结一下,文档里面 script 标签,在两种情况下不会影响文档解析:

  1. 设置了 defer 属性
  2. 设置了 async 属性,并且脚本请求完成时,文档已经解析完成了

外部样式表

样式表通常不会影响 html 文档解析。

浏览器的工作原理文章里面,提到样式表理论上不会改变 DOM 树,因此 html 解析的时候不会等待样式表。

但是脚本在文档解析阶段去请求样式信息,此时还没有加载和解析样式,脚本就会得到错误的结果。所以是否影响文档解析这里要区分一下样式表的不同情况。

1. 样式表后面紧跟着 script 脚本

<html lang=en>
 <head>
     <link rel="stylesheet" href="//8.idqqimg.com/edu/assets/css/common_css_e582a1d4.css">
     <script>console.log(121212)</script>
 </head>
 <body>
   <p>23233</p>
 </body>
</html>
复制代码

从 chrome 开发者工具里面的 Performance 分析看:

蓝色竖线 DCL,表示触发 DOMContentLoaded 时刻, 也就是说在 css 加载完成后触发的。

蓝色 Parse Stylesheet 部分,表示解析前面下载完成的样式表。

黄色 Evaluate Script 部分,执行脚步,从下面的 Summary 可以定位到刚好是第 4 行执行 console.log。

这种情况下是影响了文档解析。

2. 样式表后面没有 script 脚本

<html lang=en>
 <head>
     <script>console.log(121212)</script>
     <link rel="stylesheet" href="//8.idqqimg.com/edu/assets/css/common_css_e582a1d4.css">
 </head>
 <body>
   <p>23233</p>
 </body>
</html>
复制代码

还是从 Performance 分析:

蓝色竖线DCL几乎与css网络请求同时进行的,可以肯定样式加载没有影响到文档解析。

总结一下,通过上面两种页面,在Performance工具里面的DCL指标线,可以非常明显的看出来,外部样式表在某种情况也会影响页面解析,后面我们从HTML5规范里面找到一些说明。

HTML5 规范

文档解析部分,直接看最后解析结束部分,html.spec.whatwg.org/multipage/p…

到文档解析后面,主要看看几个步骤,到第三步:

第 3 步,update document readiness 主要更新当前文档的 readyState 值,触发 readystatechange 事件

第 5 步,遍历所有待执行的 script 列表并执行,这里提到了 has no style sheet that is blocking scripts,必须是没有阻塞脚本的样式表存在才会去执行 script。

第 6 步,才会去触发 DOMContentLoaded 事件。

再到前面 script 脚本执行部分,html.spec.whatwg.org/multipage/p…

到 otherwise 里面,脚本执行会阻止文档解析,如果脚本没有被设置 "ready to be parser-executed" 或者文档中存在阻止脚本执行的样式表,脚本执行也不会进行下去了。从这条解析路线看,的确会出现样式表阻止文档解析的情况。

但是,不一定会一直等待样式表加载。再到 a style sheet that is blocking scripts 具体定义部分:

html.spec.whatwg.org/multipage/s…

用户代理可以随时主动放弃加载样式表,提示部分提到了样式表改变元素颜色成绿色,但是如果脚本在样式表加载之前就去获取颜色,就会得到默认的黑色,影响整个页面效果。实现者必须要权衡脚本获取到错误的样式和在等待缓慢网络请求时没有执行任何解析的性能影响之间的平衡。当然这也可以是页面性能优化的一点。

最后

为什么要分析影响文档加载的因素呢?肯定是为了更好的优化页面加载性能。

分别从优化 Javascript 加载和 CSS 发送两个角度分析,进行优化,具体优化建议可以看下面链接文章。

参考記事

おすすめ

転載: juejin.im/post/7087908022378299400