Document parsing and DOMContentLoaded trigger timing

Introduction Everyone knows that after the HTML document is completely loaded and parsed, the DOMContentLoaded event will be triggered, so how does the content in the HTML affect the document parsing? Will parsing be affected when script tags or link tags are encountered during parsing? Let's analyze it together with the HTML5 specification through examples of different situations.

DOMContentLoaded trigger definition

After the HTML document is fully loaded and parsed, the DOMContentLoaded event will be triggered. Usually, the external style sheet and the image loading in the document will not affect the event triggering, but there are special cases, which we will mention later.

If a script tag is encountered, it will stop the document parsing and run the script, because the script may change the DOM, such as some document.write operations, but the script tag with the async attribute set will not affect the event triggering.

The following is a detailed analysis of the trigger timing of DOMCOntentLoaded in some scenarios.

script tag

The document parsing behavior will be different depending on the different attribute settings of the script tag,

The part about the script tag attribute in the HTML5 specification:  html.spec.whatwg.org/multipage/s…

The main async and defer properties are:

  1. async: When the script is available, it will be executed immediately, and parsing will not be blocked in the process of requesting resources. After the resource request is completed, if the document has not been parsed at this time, parsing will be blocked. Only if the script request takes longer than the document parsing time, it will not affect
  2. defer: defer script execution to ensure that document parsing is not blocked, which means that even if the script is completed from the network request, it will not be executed immediately, only after the document parsing is completed.

Their attribute values ​​are all boolean and are only valid if the src attribute is present.

The parsing time chart seen in the specification is very clear. The red line represents script script parsing, green represents html parsing, and blue represents network resource requests.

没设置属性的时候,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 发送两个角度分析,进行优化,具体优化建议可以看下面链接文章。

Reference article

Guess you like

Origin juejin.im/post/7087908022378299400