关键渲染路径

287 阅读4分钟

人是真的不能闲下来,一闲下来身体就容易虚。上周自己感冒发烧拉肚子,这周轮到家里的小朋友感冒发烧,貌似是被老母亲我传染的。嗨!

言归正传,曾经网络上有一道很热门的面试题叫做:在地址栏里输入一个URL,到这个页面呈现出来,中间会发生什么?我那个时候也认真去了解了一下网络上的答案,也学到了不少 -- 关键渲染路径。感谢这个知识点,让我后来做前端页面性能提升的时候不再像无头苍蝇一样无所下手了。

回答这个问题,我应该会从 数据请求 和 数据处理 这两块来回答。

数据请求

数据请求部分,说句实话,我本人一直不擅长。借用网络上一张图可能更清晰一点。

1508441-20201127152607474-234784821.png

数据处理

数据处理也就是客户端的渲染,即关键渲染路径。这一部分,又可以分为下面5个步骤:

  1. 处理 HTML 标记并构建 DOM 树
  2. 处理 CSS 标记并构建 CSSOM 树
  3. 将 DOM 和 CSSOM 合并成一个渲染树
  4. 根据生成的渲染树,进行布局(Layout),得到节点的几何信息(位置,大小)
  5. 根据渲染树以及回流得到的几何信息,得到节点的绝对像素

也就是下面这张图

v2-cc246d9bb0039fefbf847306118b51de_r.jpg

那图上 Script 部分是什么呢?

其实在渲染过程中,如果遇到 <script> 就会停止渲染,开始执行 JS 代码。因为浏览器有 GUI渲染线程与 JS引擎线程,为了防止渲染出现不可预期的结果,这两个线程其实是互斥关系。JS的加载、解析与执行会阻塞 DOM的构建,也就是说,在构建 DOM时,HTML 解析器如果遇到了 JS,那么它会暂停构建 DOM,将控制权移交给 JS引擎。等 JS引擎运行完毕,浏览器再从中断的地方恢复 DOM构建。这就是为啥建议将 sript 标签放在 body 标签底部的原因。

当然了,JS文件不只是阻塞 DOM的构建,它也会导致 CSSOM也阻塞 DOM的构建。

一直以来 DOM和 CSSOM的构建是互不影响的,但是一旦引入了 JS,CSSOM也开始阻塞 DOM的构建,只有 CSSOM构建完毕后,DOM再恢复DOM的构建。这是因为 JS不只是可以修改 DOM,它还可以修改样式,也就是说它可以更改 CSSOM。因为不完整的 CSSOM是无法使用的,如果 JS想访问 CSSOM并更改它,那么在执行 JS时,必须要能拿到完整的 CSSOM。这就会导致一个现象,如果浏览器尚为完成 CSSOM的下载和构建,而此时我们想运行脚本,那么 sorry~浏览器将延迟脚本执行和 DOM的构建,直到完成 CSSOM的下载和构建。也就是说,在这种情况下,浏览器会优先下载和构建 CSSOM,然后再执行 JS,最后再继续构建 DOM。

那图片中 reflow layout又是怎么一回事呢?

通常第一次页面加载完之后,把东西放到页面上去,这个过程叫做布局(layout)。如果说是由于之后页面上又发生了一些视觉的变化,又导致再次布局,这个过程叫做回流(reflow)。

那么什么样的操作会导致回流的发生呢?布局这一个阶段主要是计算节点的位置和几何信息,所以只有当页面布局和几何信息发生变化的时候,就会发生回流。

比如一下几个情况会发生回流:

  • 添加/删除元素
  • display:none
  • 移动元素位置
  • 操作 styles
  • offsetLeft, scrollTop, clientWidth
  • 修改浏览器大小,字体大小
那么什么情况下会发生重绘而不回流呢?

当页面中元素样式的改变并不会影响它在文档流中的位置时(比如 color、background-color、visibility等),浏览器会将新样式赋予给元素并重新绘制它,这个过程就是重绘而不回流。

PS:回流是一定会触发重绘,而重绘不一定会回流

参考文章: 你真的了解回流和重绘吗