什么时候解析HTML DOM树?

Jas*_*eOT 29 html javascript dom

我总是看到一个网页的渲染流程,如下图所示: 在此输入图像描述

因此,绘画只在解析DOM树并创建CSSOM后才开始,对吧?另一种说法是,<script>最后的<body>做法是最佳实践,以便在下载脚本之前页面呈现内容.

我的问题是,什么时候解析DOM树,我们怎么说它已经完成了?在我的理解<script>中,最终也是DOM树的一部分,只有加载了脚本才能调用DOM树创建.浏览器从上到下读取html文件,创建DOM树,当它看到时<script>,它停止下载并执行它,直到解析遍历整个页面.或者,页面是否在解析DOM树的同时绘制页面?

pes*_*sla 13

TL; DR:收到文档后,解析即刻开始.

解析和绘画

有关更详细的说明,我们需要深入了解渲染引擎的工作方式.

渲染引擎解析HTML文档并创建两个树:the content tree和the render tree.内容树包含所有DOM节点.渲染树包含所有样式信息(CSSOM),包含渲染页面所需的DOM节点.

一旦创建了渲染树,浏览器就会经历两个过程:应用layoutpainting每个DOM节点.应用布局意味着计算DOM节点应出现在屏幕上的精确坐标.绘画意味着实际渲染像素并应用风格属性.

这是一个渐进的过程:浏览器不会等到所有HTML都被解析.将解析和显示部分内容,同时继续处理来自网络的其余内容.

您可以在浏览器中看到此过程.例如,打开Chrome开发者工具并加载您选择的网站.

网络选项卡

Network选项卡中记录活动后,您会注意到下载文档时开始解析.它识别资源并开始下载它们.蓝色垂直线表示DOMContentLoaded事件,红色垂直线表示load事件.

时间线选项卡

记录时间表可以让您更深入地了解幕后发生的事情.我已将上面的屏幕截图作为示例包含,以指示在解析文档时发生绘画.请注意,初始绘制就在它继续解析文档的另一部分之前发生.此过程一直持续到文档结束.

单线程

渲染引擎是单线程的.除了网络操作之外,几乎所有事情都发生在这个线程中.

将其与网络的同步性结合起来.开发人员希望<script>立即解析并执行(即:解析器一旦到达脚本标记).这意味着:

  1. 必须从网络获取资源(由于DNS查找和连接速度,这可能是一个缓慢的过程).
  2. 资源的内容将传递给Javascript解释器.
  3. 解释器解析并执行代码.

解析文档会暂停,直到此过程结束.您不会通过<script>在文档末尾包含's来改善总解析时间.它确实增强了用户体验,因为解析和绘制过程不会被<script>需要执行的过程中断.

通过使用defer和/或标记资源可以解决此问题async.async在HTML解析期间下载文件,并在完成下载后暂停HTML解析器执行它.defer在HTML解析期间下载文件,并且只在解析器完成后才执行它.

推测性解析

一些浏览器旨在<script>通过使用所谓的推测解析来解决阻塞问题.在下载和执行脚本时,引擎会向前解析(并运行HTML树构造!).Firefox和Chrome使用这种技术.

如果推测成功,您可以想象性能提升(例如,DOM没有被文档中包含的脚本改变).等待脚本执行不是必需的,页面已成功绘制.不利的一面是,当投机失败时,会有更多的工作损失.

对我们来说幸运的是,非常聪明的人会使用这些技术,所以即使document.write正确使用也不会破坏这个过程.另一个经验法则是不使用document.write.例如,它可以破坏推测树:

// Results in an unbalanced tree
<script>document.write("<div>");</script>

// Results in an unfinished token
<script>document.write("<div></div");</script>
Run Code Online (Sandbox Code Playgroud)

进一步阅读

以下资源值得您花时间阅读: