Open
Description
一、为啥优化CSS
1. 阻塞渲染树构建
未构建完的CSSOMTree是不准确的,浏览器必须等到CSSOMTree构建完毕后才能进入下一阶段。
阻塞渲染的 CSS说道:
CSS 是阻塞渲染的资源。需要将它尽早、尽快地下载到客户端,以便缩短首次渲染的时间
This means that the browser needs to wait for all CSS to load and get processed before painting a single pixel on the screen
2. 阻塞DOM
树构建(主要是首屏渲染)
讲故事:
- 页面里只有HTML和CSS时,CSSOM和DOM是各自创建的,互不干扰。
- 后来有了JS(即使是空
script
标签)。
JS可以除了可以操作DOM外,还可以操作CSSOM啊,并且CSSOM必须完全构建后才能使用。所以JS等待CSSOM构建。JS不执行完DOM树构建也被阻塞了(此时CSSOM构建间接地阻塞DOM树构建渲染)。 - JS优化了:
asnc/defer
的script
标签声明不操作DOM,也不操作CSSOM。
二、优化手段
-
关键CSS直接写到页面里
不使用外部文件加载关键CSS可减少http请求数量,但这样会增加文档体积,增加了DOM
解析时间。 -
非关键CSS延迟加载
<link rel="preload" as="style" href="styles.css" onload="this.rel='stylesheet';this.onload=null;">
- 媒体查询
不符合媒体查询的CSS都不阻塞渲染,只是异步下载,但不会解析CSS(即不应于页面)。
<link rel="stylesheet" href="/path/to/my.css" media="print" onload="this.media='all'; this.onload=null;">
本质上preload
和媒体查询这两种方式异曲同工。
- 外部CSS文件压缩。
总之:减小CSS文件体积,尽早、尽快地下载到客户端,以便缩短首次渲染的时间。
Demo1
知乎 浏览器的渲染过程有个间接阻塞的例子
Demo2
阻塞DOM构建
<!DOCTYPE html>
<html>
<head>
<title>Normal</title>
<link rel="stylesheet" href="./lib/style.css"/>
</head>
<body>
<p>...content before scripts...</p>
<p>...content after scripts...</p>
<p>...content after document.write scripts...</p>
<script src="./lib/normal.long.js"></script>
</body>
</html>
优化(给script
加defer
)后不阻塞DOM树构建:
<!DOCTYPE html>
<html>
<head>
<title>Normal</title>
<link rel="stylesheet" href="./lib/style.css"/>
</head>
<body>
<p>...content before scripts...</p>
<p>...content after scripts...</p>
<p>...content after document.write scripts...</p>
<script defer src="./lib/normal.long.js"></script>
</body>
</html>
检测关键CSS(一般首屏渲染依赖的CSS)
工具
案例分析
淘宝
- CSS 直接写入页面,并且样式图片和字体文件也是base64数据
- 没有外部CSS
JD
- 样式直接在组件模块里
- 也有外部样式
FB
- 部分CSS利用了
repload
; - CSS数据居然使用base64数据;
总体看下来大部分首屏样式直接写到页面里了,但是利用preload
加载样式的比较少,到时利用preload
加载js的比较多。