浏览器的关键渲染路径

TLDR,页面的关键渲染路径:

从浏览器接收到 HTML内容时便开始了这一系列的工作。理解浏览器渲染过程是优化 Web 性能的基础。

构建对象模型

浏览器接收到 HTML、CSS 后便开始了对象模型的构建。

对象模型(Object Model)是一种数据结构,HTML 和 CSS 都可以通过对象模型来描述。HTML 会被浏览器解析构建为 DOM,CSS 则会被解析构建为 CSSOM。

他们都遵循一套类似的解析、构建流程:

文档对象模型 DOM

CSS 对象模型 CSSOM

有了 CSSOM 浏览器就可以在在渲染时从节点最通用规则开始(如果该节点是 body 的子元素,则应用所有 body 样式),然后向更具体的规则(向下级联)递归的优化计算的样式。

需要注意的是,通过用户的样式表构建出来的还不是一个完整的 CSSOM,还需要与浏览器默认样式(User agent style)进行合并后才能得到完整的 CSSOM。

预加载扫描器

在浏览器构建 DOM 过程中并不是解析到了 link、script 标签才开始加载对应的外部资源,而是会进行预加载扫描,使得关键资源能提前加载减少阻塞时间。

查看构建对象模型的耗时

构建对象模型的耗时与文档内容息息相关,我们可以通过浏览器调试工具来观察渲染过程和耗时情况。

构建渲染树

当 DOM 和 CSSOM 构建完成后浏览器将会对他们进行合并,组成一颗渲染树(Render tree)。

DOM 包含了文档内所有的节点,但 Render tree 会通过 CSSOM 来过滤掉不需要渲染的节点。这些不需要渲染的节点例如某些 meta 标签、注释和被 CSS 隐藏的元素等。

需要注意的是 visibility: hidden 的元素虽然会被隐藏但还是占据着自身的位置,是会被包含在渲染树中的。

布局

渲染树构建完成后就进入到布局(Layout)阶段。浏览器从渲染树的根节点开始进行遍历,通过盒模型来计算渲染树中所有节点元素的的宽度、高度及页面上的位置,并将所有相对测量值都转换为屏幕上的绝对像素。

第一次确定节点的大小和位置称为布局。随后对节点大小和位置的重新计算称为回流。

渲染

最后的步骤则是将节点绘制到屏幕上。

浏览器绘制页面的时间取决于页面内容的多少和样式复杂程度。例如绘制普通的边框要比绘制阴影速度要快上许多。

另外,为了提升重绘的速度,浏览器还会将绘制内容进行分层,使得重绘时仅绘制必要的内容,通过分层绘制时还需要对页面中重叠的部分进行合成。分层可以提高性能,但是它以内存管理为代价。

为了保证页面的流畅我们需要以每秒 60 帧刷新页面。也就是说从每一次构建对象模型、计算样式、回流、重绘需要在 16.66ms 内完成,超过这个时间用户则会感觉到页面卡顿。

关键渲染路径

浏览器渲染页面的流程:构建 DOM、构建 CSSOM、构建渲染树、布局、绘制。

这五个关键流程也叫做浏览器的 “关键渲染路径”

上面仅仅是理想情况下的页面渲染过程,实际上会有许多 “东西” 阻塞关键渲染路径,我们对 Web 性能的优化也是围绕着关键渲染路径来展开的。