浏览器原理 22 # 渲染流水线:CSS如何影响首次加载时的白屏时间?
Posted 凯小默
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了浏览器原理 22 # 渲染流水线: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>
渲染流水线示意图:
- 请求 HTML 数据和构建 DOM 中间有一段空闲时间,这个空闲时间有可能成为页面渲染的瓶颈
- 在 DOM 构建结束之后、
theme.css
文件还未下载完成的这段时间内,渲染流水线处于空闲状态 - 合成布局树需要 CSSOM 和 DOM,需要等待 CSS 加载结束并解析成 CSSOM
CSSOM
那渲染流水线为什么需要 CSSOM 呢?
和 HTML 一样,渲染引擎也是无法直接理解 CSS 文件内容的,所以需要将其解析成渲染引擎能够理解的结构,这个结构就是 CSSOM。
CSSOM 的作用
- 提供给 javascript 操作样式表的能力
- 为布局树的合成提供基础的样式信息
含有 JavaScript 和 CSS 的页面渲染流水线
//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>
如果页面中包含了外部 CSS 文件的引用,或者通过 style 标签内置了 CSS 内容,那么渲染引擎还需要将这些内容转换为 CSSOM。
CSS 在部分情况下也会阻塞 DOM 的生成。因为在执行 JavaScript 之前,还需要依赖 CSSOM。
含有 JavaScript 文件和 CSS 文件页面的渲染流水线
两个文件的下载过程是重叠的,所以下载时间按照最久的那个文件来算。
//theme.css
div{
color : coral;
background-color:black
}
//foo.js
console.log('time.geekbang.org')
<html>
<head>
<link href="theme.css" rel="stylesheet">
</head>
<body>
<div>geekbang com</div>
<script src='foo.js'></script>
<div>geekbang com</div>
</body>
</html>
不管 CSS 文件和 JavaScript 文件谁先到达,都要先等到 CSS 文件下载完成并生成 CSSOM,然后再执行 JavaScript 脚本,最后再继续构建 DOM,构建布局树,绘制页面。
影响页面展示的因素以及优化策略
从发起 URL 请求开始,到首次显示页面的内容,在视觉上经历的三个阶段:
- 第一个阶段:等请求发出去之后,到提交数据阶段,这时页面展示出来的还是之前页面的内容。
- 第二个阶段:提交数据之后渲染进程会创建一个空白页面,通常把这段时间称为解析白屏,并等待 CSS 文件和 JavaScript 文件的加载完成,生成 CSSOM 和 DOM,然后合成布局树,最后还要经过一系列的步骤准备首次渲染。
- 第三个阶段:等首次渲染完成之后,就开始进入完整页面的生成阶段了,然后页面会一点点被绘制出来。
影响第一个阶段的因素主要是:网络或者是服务器处理。影响第三个阶段后续在分析。
重点看一下第二个阶段。
这个阶段的主要问题是白屏时间,如果白屏时间过久,就会影响到用户体验。
怎么缩短白屏时间?
第二个阶段的主要任务包括了:解析 HTML、下载 CSS、下载 JavaScript、生成 CSSOM、执行 JavaScript、生成布局树、绘制页面一系列操作。
通常情况下的瓶颈主要体现在下载 CSS 文件、下载 JavaScript 文件和执行 JavaScript。
策略:
- 通过内联 JavaScript、内联 CSS 来移除这两种类型的文件下载,这样获取到 HTML 文件之后就可以直接开始渲染流程了。
- 但并不是所有的场合都适合内联,那么还可以尽量减少文件大小,比如通过 webpack 等工具移除一些不必要的注释,并压缩 JavaScript 文件。
- 还可以将一些不需要在解析 HTML 阶段使用的 JavaScript 标记上 async 或者 defer。
- 对于大的 CSS 文件,可以通过媒体查询属性,将其拆分为多个不同用途的 CSS 文件,这样只有在特定的场景下才会加载特定的 CSS 文件。
以上是关于浏览器原理 22 # 渲染流水线:CSS如何影响首次加载时的白屏时间?的主要内容,如果未能解决你的问题,请参考以下文章