渲染流水线:CSS如何影响首次加载时的白屏时间?
渲染流水线视角下的 CSS
//theme.css
div{
color : coral;
background-color:black
}
geekbang com
这两段代码分别由 CSS 文件和 HTML 文件构成,我们来分析下打开这段 HTML 文件时的渲染流水线,你可以先参考下面这张渲染流水线示意图:
含有 CSS 的页面渲染流水线
下面我们结合上图来分析这个页面文件的渲染流水线。
首先是发起主页面的请求,这个发起请求方可能是渲染进程,也有可能是浏览器进程,发起的请求被送到网络进程中去执行。
网络进程接收到返回的 HTML 数据之后,将其发送给渲染进程,渲染进程会解析 HTML 数据并构建 DOM。
其中,请求 HTML 数据和构建 DOM 中间有一段空闲时间,这个空闲时间有可能成为页面渲染的瓶颈。
上一篇文章中我们提到过,当渲染进程接收 HTML 文件字节流时,会先开启一个预解析线程,如果遇到 JavaScript 文件或者 CSS 文件,那么预解析线程会提前下载这些数据。预解析线程会解析出一个外部的theme.css文件,并发起theme.css文件的下载。
css解析是在构建dom之后的,cssdom构建阶段才用,所以在这个dom构建阶段需要等待。
那渲染流水线为什么需要 CSSOM 呢?
和 HTML 一样,渲染引擎也是无法直接理解 CSS 文件内容的,所以需要将其解析成渲染引擎能够理解的结构,这个结构就是 CSSOM。
CSSOM 也具有两个作用,第一个是提供给 JavaScript 操作样式表的能力,第二个是为布局树的合成提供基础的样式信息。
- 我们再来看看更加复杂一点的情况,如果在 body 中被包含的是 JavaScript 外部引用文件,Demo 代码如下所示:
//theme.css
div{
color : coral;
background-color:black
}
//foo.js
console.log('time.geekbang.org')
geekbang com
geekbang com
从上面代码可以看出来,HTML 文件中包含了 CSS 的外部引用和 JavaScript 外部文件,那它们的渲染流水线是怎样的呢?可参考下图:
从上图可以看出,在接收HTML数据之后,有CSS文件和JavaScript文件同时需要加载,然后就同时发起这两个文件的下载请求,需要注意的是,这两个文件的下载过程是重叠的,所以下载时间按照最久的那个文件来算。
影响页面展示的因素以及优化策略
前面我们为什么要花这么多文字来分析渲染流水线呢?主要原因就是渲染流水线影响到了首次页面展示的速度,而首次页面展示的速度又直接影响到了用户体验。
目的就是为了找出一些影响到首屏展示的因素,对此做一些针对性优化。
那么接下来我们就来看看从发起 URL 请求开始,到首次显示页面的内容,在视觉上经历的三个阶段。
- 第一个阶段,等请求发出去之后,到提交数据阶段,这时页面展示出来的还是之前页面的内容。关于提交数据你可以参考前面《04 | 导航流程:从输入 URL 到页面展示,这中间发生了什么?》这篇文章。
- 第二个阶段,提交数据之后渲染进程会创建一个空白页面,我们通常把这段时间称为解析白屏,并等待 CSS 文件和 JavaScript 文件的加载完成,生成 CSSOM 和 DOM,然后合成布局树,最后还要经过一系列的步骤准备首次渲染。
- 第三个阶段,等首次渲染完成之后,就开始进入完整页面的生成阶段了,然后页面会一点点被绘制出来。
影响第一个阶段的因素主要是网络或者是服务器处理这块儿
至于第三个阶段,我们会在后续文章中分析,所以这里也不做介绍了。
现在我们重点关注第二个阶段,这个阶段的主要问题是白屏时间,如果白屏时间过久,就会影响到用户体验。为了缩短白屏时间,我们来挨个分析这个阶段的主要任务,包括了解析 HTML、下载 CSS、下载 JavaScript、生成 CSSOM、执行 JavaScript、生成布局树、绘制页面一系列操作。
通常情况下的瓶颈主要体现在下载 CSS 文件、下载 JavaScript 文件和执行 JavaScript。
所以要想缩短白屏时长,可以有以下策略:
- 通过内联 JavaScript、内联 CSS 来移除这两种类型的文件下载,这样获取到 HTML 文件之后就可以直接开始渲染流程了。
- 但并不是所有的场合都适合内联,那么还可以尽量减少文件大小,比如通过 webpack 等工具移除一些不必要的注释,并压缩 JavaScript 文件。
- 还可以将一些不需要在解析 HTML 阶段使用的 JavaScript 标记上 sync 或者 defer。
- 对于大的 CSS 文件,可以通过媒体查询属性,将其拆分为多个不同用途的 CSS 文件,这样只有在特定的场景下才会加载特定的 CSS 文件。
通过以上策略就能缩短白屏展示的时长了,不过在实际项目中,总是存在各种各样的情况,这些策略并不能随心所欲地去引用,所以还需要结合实际情况来调整最佳方案。
此文章为4月Day19学习笔记,内容来源于极客时间《浏览器原理》,学习使我快乐,每天进步一点点💪💪
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net