浏览器工作原理--渲染流水线:CSS如何影响首次加载时的白屏时间?

一、渲染流水线视角下的 CSS

//theme.css
div{ 
    color : coral;
    background-color:black
}
<html>
<head>
    <link href="theme.css" rel="stylesheet">
</head>
<body>
    <div>geekbang com</div>
</body>
</html>

(1)含有 CSS 的页面渲染流水线

1、首先是发起主页面的请求,这个发起请求方可能是渲染进程,也有可能是浏览器进程,发起的请求被送到网络进程中去执行。

2、网络进程接收到返回的 HTML 数据之后,将其发送给渲染进程,渲染进程会解析 HTML 数据并构建 DOM。这里你需要特别注意下,请求 HTML 数据和构建 DOM 中间有一段空闲时间,这个空闲时间有可能成为页面渲染的瓶颈。

3、当渲染进程接收 HTML 文件字节流时,会先开启一个预解析线程,如果遇到 JavaScript 文件或者 CSS 文件,那么预解析线程会提前下载这些数据。对于上面的代码,预解析线程会解析出来一个外部的 theme.css 文件,并发起 theme.css 的下载。

4、这里也有一个空闲时间需要你注意一下,就是在 DOM 构建结束之后、theme.css 文件还未下载完成的这段时间内,渲染流水线无事可做,因为下一步是合成布局树,而合成布局树需要 CSSOM 和 DOM,所以这里需要等待 CSS 加载结束并解析成 CSSOM。

(2)渲染流水线为什么需要 CSSOM 呢?

1、和 HTML 一样,渲染引擎也是无法直接理解 CSS 文件内容的,所以需要将其解析成渲染引擎能够理解的结构,这个结构就是 CSSOM

2、和 DOM 一样,CSSOM 也具有两个作用,第一个是提供给 JavaScript 操作样式表的能力,第二个是为布局树的合成提供基础的样式信息。这个 CSSOM 体现在 DOM 中就是document.styleSheets。

(3)有了 DOM 和 CSSOM,接下来就可以合成布局树了

1、等 DOM 和 CSSOM 都构建好之后,渲染引擎就会构造布局树

2、布局树的结构基本上就是复制 DOM 树的结构,不同之处在于 DOM 树中那些不需要显示的元素会被过滤掉,如 display:none 属性的元素、head 标签、script 标签等。

3、复制好基本的布局树结构之后,渲染引擎会为对应的 DOM 元素选择对应的样式信息,这个过程就是样式计算

4、样式计算完成之后,渲染引擎还需要计算布局树中每个元素对应的几何位置,这个过程就是计算布局

5、通过样式计算和计算布局就完成了最终布局树的构建。再之后,就该进行后续的绘制操作了

二、 稍微复杂一点CSS的场景

HTML 文件中包含了 CSS 的外部引用和 JavaScript 外部文件:

//theme.css
div{ 
    color : coral;
    background-color:black
}
<html>
<head>
    <link href="theme.css" rel="stylesheet">
</head>
<body>
    <div>geekbang com</div>
    <script>
        console.log('time.geekbang.org')
    </script>
    <div>geekbang com</div>
</body>
</html>

(1)含有 JavaScript 文件和 CSS 文件页面的渲染流水线

1、在接收到 HTML 数据之后的预解析过程中,HTML 预解析器识别出来了有 CSS 文件和 JavaScript 文件需要下载,然后就同时发起这两个文件的下载请求,需要注意的是,这两个文件的下载过程是重叠的,所以下载时间按照最久的那个文件来算。

2、后面的流水线就和前面是一样的了,不管 CSS 文件和 JavaScript 文件谁先到达,都要先等到 CSS 文件下载完成并生成 CSSOM,然后再执行 JavaScript 脚本,最后再继续构建 DOM,构建布局树,绘制页面

三、影响页面展示的因素以及优化策略

(1)优化原因

渲染流水线影响到了首次页面展示的速度,而首次页面展示的速度又直接影响到了用户体验。

(2)从发起 URL 请求开始,到首次显示页面的内容,在视觉上经历的三个阶段。

  • 第一个阶段,等请求发出去之后,到提交数据阶段,这时页面展示出来的还是之前页面的内容。
  • 第二个阶段,提交数据之后渲染进程会创建一个空白页面,我们通常把这段时间称为解析白屏,并等待 CSS 文件和 JavaScript 文件的加载完成,生成 CSSOM 和 DOM,然后合成布局树,最后还要经过一系列的步骤准备首次渲染。
  • 第三个阶段,等首次渲染完成之后,就开始进入完整页面的生成阶段了,然后页面会一点点被绘制出来。

1、影响第一个阶段的因素主要是网络或者是服务器处理。(第一种服务器的问题,你可以想办法去提高服务器的处理速度,比如通过增加各种缓存的技术;第二种网络问题,你可以使用 CDN 来缓存一些静态文件;至于第三种,你在发送请求时就去尽可能地减少一些不必要的 Cookie 数据信息。)

2、第二个阶段主要问题是白屏时间,如果白屏时间过久,就会影响到用户体验。为了缩短白屏时间,我们来挨个分析这个阶段的主要任务,包括了解析 HTML、下载 CSS、下载 JavaScript、生成 CSSOM、执行 JavaScript、生成布局树、绘制页面一系列操作。通常情况下的瓶颈主要体现在下载 CSS 文件、下载 JavaScript 文件和执行 JavaScript。

所以要想缩短白屏时长,可以有以下策略:

  • 通过内联 JavaScript、内联 CSS 来移除这两种类型的文件下载,这样获取到 HTML 文件之后就可以直接开始渲染流程了。
  • 但并不是所有的场合都适合内联,那么还可以尽量减少文件大小,比如通过 webpack 等工具移除一些不必要的注释,并压缩 JavaScript 文件。
  • 还可以将一些不需要在解析 HTML 阶段使用的 JavaScript(JavaScript 文件中没有操作 DOM 相关代码) 标记上 async 或者 defer。(都是异步的,async一旦加载,立即执行,defer,再DOMContentLoaded事件之前执行)
  • 对于大的 CSS 文件,可以通过媒体查询属性,将其拆分为多个不同用途的 CSS 文件,这样只有在特定的场景下才会加载特定的 CSS 文件。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值