资讯专栏INFORMATION COLUMN

前端渲染过程的二三事

Rindia / 2070人阅读

摘要:前端渲染过程的二三事本文不会介绍整个前端渲染过程的步骤,只是记录最近阅读的文章的些许思考和感悟。那么现在我们可以明白这个问题的关键所在了,因为在大部分页面中是拥有的,而由于其解析顺序,那么在事件之前必定已经成功构造树。

前端渲染过程的二三事

本文不会介绍整个前端渲染过程的步骤,只是记录最近阅读的文章的些许思考和感悟。(文章地址一(系列),文章地址二)

希望大家在阅读这篇文章之前能将上述文章仔细浏览一篇,因为本文所述基本是基于其内容。

Navigation Timing API和浏览器加载事件

Navigation Timing API:可通过打印(performance)查看;

浏览器加载事件:domContentLoaded,onload

上图整理了Navigation Timing API中的一些事件和浏览器加载事件的发生顺序。

这些事件的含义是什么呢?我们直接引用文章地址一(系列)的介绍:

domLoading:这是整个过程的起始时间戳,浏览器即将开始解析第一批收到的 HTML 文档字节。

domInteractive:表示浏览器完成对所有 HTML 的解析并且 DOM 构建完成的时间点。

domContentLoaded:表示 DOM 准备就绪并且没有样式表阻止 JavaScript 执行的时间点,这意味着现在我们可以构建渲染树了。

许多 JavaScript 框架都会等待此事件发生后,才开始执行它们自己的逻辑。因此,浏览器会捕获 EventStart 和 EventEnd 时间戳,让我们能够追踪执行所花费的时间。

domComplete:顾名思义,所有处理完成,并且网页上的所有资源(图像等)都已下载完毕,也就是说,加载转环已停止旋转。

loadEvent:作为每个网页加载的最后一步,浏览器会触发 onload 事件,以便触发额外的应用逻辑。

看了上述事件的介绍,大致了解了每个事件所代表的含义,但也带着少许疑惑:

HTML解析是分批进行的吗?为什么要分批进行?

domContentLoaded事件结束后可以构建渲染树了,是否意味着CSSOM树构建也在该事件之前就已完成?

domContentLoaded事件表示DOM准备就绪并且没有样式表阻止 JavaScript执行的时间点,可是JavaScript执行是在构建DOM树之前,那这是不是意味着该事件在DOM树构建完成后就执行了?若是这与domInteractive事件有什么区别呢?

首先看第一个问题,我们直接用chrome控制台的performance来看效果。


上图中,上方的Network的蓝条是HTML的下载时间,下方箭头所指是HTML的解析时间。

从中我们可以得出HTML解析的确是分批进行,并且解析并不需要等HTML完全下载完。那为什么要分批进行呢?这个问题我找了许多资料也没有得出结论,于是自己从中思考。假设不是分批进行,那实现会有两种情况:1.等HTML全部下载完,再一起解析;2.每下载一定量的HTML就将其放入解析器等待排队解析。前者首先肯定被排除,若HTML很大,会影响首屏加载速度,后者按理速度更快,或许其实现的难度以及可能会带来的一些问题而没有采用?这个问题思考了良久,感觉从理论上是可行的,但从技术角度,由于自己这方面的知识实在薄弱,所以也无法得知其实现的过程是否存在技术瓶颈。

第二个问题:CSSOM树构建是否在domContentLoaded事件之前?

话不多说我们自己实践。

首先我先创建一个HTML文件并写入少许标签,再创建一个CSS并于HTML引入,在CSS文件中写入大量内容(自己实践时写了5W多行)。然后用performance查看。

上图每个箭头代表的含义:

HTML解析结束时间

domContentLoaded加载时间

CSS文件下载完的时间

CSS文件解析的时间

从这个步骤以及其所处时间,我们可以清晰的得出,该结论不准确。那么该作者为什么会得出该结论呢,是他犯错了吗?我随后发现他在这篇文章下面还写了一句“domContentLoaded一般表示DOM和CSSOM均准备就绪的时间点”。那么这句话意味着大部分的时候CSSOM树的构建是在domContentLoaded事件之前。可是这个大部分又指的是什么情况,这又涉及到另一个知识点“DOM树,CSSOM树,JS的三角关系”,构造DOM树时遇见JS会先解析执行JS,而在解析执行JS时遇到CSSOM,又会先构造CSSOM树,这个过程稍后会具体说明。那么现在我们可以明白这个问题的关键所在了,因为在大部分页面中是拥有JS的,而由于其解析顺序,那么在domContentLoaded事件之前必定已经成功构造CSSOM树。

第三个问题:domInteractive与domContentLoaded的区别是什么呢?这两个事件中间是否还会进行其他操作?

我们都知道script标签有defer和async两个属性。有了这两个属性,浏览器就会加一个进程下载JS。那么下载完的执行时间点是在什么时候?其中async会在JS下载完后立马执行,也正是这个原因,会导致JS的执行顺序不一定按标签的从上至下,而是按照下载完的时间。那么defer属性的执行时间呢,我想大家应该都能猜到了,它的执行时间点的确就是在上述的两个事件之间,那么我们也就得知这两个事件的区别所在。

三大树

我们都知道前端渲染有三大树:DOM树,CSSOM树,RENDER树。那么这三大树的构造时间和上述的事件执行时间的顺序又是怎样的呢。

其中DOM树和RENDER树所在位置其实是显而易见的,并且在之前内容也已经指出。DOM树在domInteractive事件之前,RENDER树在domContentLoaded事件之后。但是CSSOM树就难以捉摸,其与DOM树的关系,完全受到是否拥有JS影响。

在确定CSSOM树所处位置前,我们先确定一个上面提到的概念:构造DOM树时遇见JS会先解析执行JS,而在解析执行JS时遇到CSSOM,又会先构造CSSOM树。官方给出的原因是,JS会使用document.write而改变DOM树,所以构造DOM树时碰到JS会先执行JS;而JS在执行时,需要查找CSS,所以执行JS时,碰到构造CSSOM树,会先构造CSSOM树。但是这里有一点奇怪的时,JS也可以通过创造Link标签的方式改变CSSOM树,所以个人感觉官方的这种解释有点牵强。不过官方的解释虽然不能让人完全信服,但这执行顺序是不会有错的。

接下来我们分别通过有无JS两大类确认CSSOM树所处位置:

无JS的情况
由于DOM树和CSSOM树是并行解析的情况,所以这两个树构建完成的顺序完全无法固定,只由它们自己本身大小有关。因此CSSOM树构建完成的时间既可能在domInteractive之前,可能在domContentLoaded之后,也可能在这两事件之间。

有JS的情况
这里我们先假设CSS文件很小,在没还解析到JS时就已完成解析,那么这种情况其实必定发生在domInteractive之前,因为都还没解析到JS,说明DOM树必定没有构建完成。那么再假设CSS文件很大,然后中途遇到JS文件,这时候JS文件发现在构造CSSOM树,其就会等待CSSOM树构建完成后再解析执行JS,所以这种情况CSSOM也必定在domInteractive之前。

但是有2个有意思的情况:

(1) 如果我们动态创建link标签并添加到html中,那么又会发生什么呢?若JS还没解析执行完,那么会停止JS而去解析CSS,若JS已执行完那么CSSOM树其实也不是必定在domInteractive之前。(当然这可能已经不算初次渲染构建)
(2) link标签放到JS后面又会发生什么呢?这种情况我发现不管我怎么尝试,CSSOM树必定在DOM树构建之前构建,但其又在JS执行完成后。如果有兴趣的同学可以查查是为什么。

总结

其实前端渲染是一个很庞大的知识点,并且其涉及的周边知识也及其庞大,本文只是对其中一个小知识点做了思考和实践。最后要说的一点是,以上内容,纯属个人见解,如有不当,请多指教。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/99186.html

相关文章

  • 数组方法的二三事

    摘要:常用的数组方法删除数组的最后一个元素,返回被删除的元素,原数组长度减。原数组发生了变化,但没有创建新的数组。将指定数组进行排序,返回排好序的数组。颠倒数组元素的顺序,返回逆序后的数组。 数组,对于每一个前端人员来说是非常常见且重要的数据结构之一,也是面试常常出现的题目,掌握数组的方法能帮助我们更高效地处理问题。不过在数组的学习中,我们常常会混淆数组本身的方法和Javascript提供的...

    VincentFF 评论0 收藏0
  • 微信小程序开发中的二三事之网易云信IMSDK DEMO

    摘要:传统的网页编程采用的三剑客来实现,在微信小程序中同样有三剑客。观察者模式不难实现,重点是如何在微信小程序中搭配其特有的生命周期来使用。交互事件传统的事件传递类型有冒泡型与捕获型,微信小程序中自然也有。 本文由作者邹永胜授权网易云社区发布。 简介为了更好的展示我们即时通讯SDK强悍的能力,网易云信IM SDK微信小程序DEMO的开发就提上了日程。用产品的话说就是: 云信 IM 小程序 S...

    weij 评论0 收藏0
  • 与dom事件流相关的二三事

    摘要:但对于整个事件流上的别的元素来说,执行顺序还会受到另外一个因素的影响。以上面的场景为例,在捕获阶段执行的事件,如果执行,则事件流终止,不会到达目标阶段,的世界则不会被执行执行结果为线上参考事件流 向dom绑定事件的事件的三种方式 行内绑定 按钮 js内绑定 btnDom.onclick = function clickHandler() { console.log(click)...

    Anleb 评论0 收藏0
  • 分表后需要注意的二三事

    摘要:分表字段的选择。问题产生之前提到在分表应用上线前我们需要将原有表的数据迁移到新表中,这样才能保证业务不受影响。虽说凌晨的业务量下降,但依然有少部分的请求过来,也会出现各种数据库异常。 showImg(https://segmentfault.com/img/remote/1460000019462791?w=496&h=285); 前言 本篇是上一篇《一次分表踩坑实践的探讨》,所以还没...

    dongxiawu 评论0 收藏0
  • 关于UUID的二三事

    摘要:规范定义来自于发布的一个规范。其中的字母是进制表示,大小写无关。在里面的使用的例子其中,最后的个字符就是我电脑网卡的地址版本安全的安全的和基于时间的算法相同,但会把时间戳的前位置换为的或。 一、简介 UUID,是Universally Unique Identifier的缩写,UUID出现的目的,是为了让分布式系统可以不借助中心节点,就可以生成UUID来标识一些唯一的信息; GUID,...

    Dr_Noooo 评论0 收藏0

发表评论

0条评论

Rindia

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<