# 资源加载顺序
CSS 和 JS 是否会阻塞页面解析渲染?
# CSS 加载会阻塞 DOM 树解析和渲染吗
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
h1 {
color: red !important;
}
</style>
<link
href="https://cdn.bootcss.com/bootstrap/4.0.0-alpha.6/css/bootstrap.css"
rel="stylesheet"
/>
<script>
function h() {
console.log(document.querySelectorAll("h1"));
}
setTimeout(h, 0);
</script>
</head>
<body>
<h1>这是红色的</h1>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
我们假设 CSS 会阻塞 DOM 树解析和渲染,那么会出现以下情况:
在 bootstrap.css 还没加载完之前,下面的内容不会被解析渲染。那么我们一开始看到的应该是白屏,h1 不会显示出来。并且此时 console.log 的结果应该是一个空数组。
# CSS 会阻塞 DOM 树解析?
打开浏览器,我们发现在 bootstrap.css 还没加载完成的时候,h1 并没有显示,但是此时控制台输出 [h1],可以得知:
DOM 树至少已经解析完成到了 h1 那里,而此时 css 还没加载完成,也就说明,CSS 并不会阻塞 DOM 树的解析。
# CSS 加载会阻塞 DOM 树渲染?
上面操作可以发现,在 CSS 未加载完之前,页面都是处于白屏,CSS 加载完后,红色字体才显示出来.下面的内容虽然解析了,但是并没有被渲染出来。所以: CSS 加载会阻塞 DOM 树渲染。
# CSS 加载会阻塞 JS 运行吗
<!DOCTYPE html>
<html lang="en">
<head>
<title>css阻塞</title>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script>
console.log("before css");
var startDate = new Date();
</script>
<link
href="https://cdn.bootcss.com/bootstrap/4.0.0-alpha.6/css/bootstrap.css"
rel="stylesheet"
/>
</head>
<body>
<h1>这是红色的</h1>
<script>
var endDate = new Date();
console.log("after css");
console.log("经过了" + (endDate - startDate) + "ms");
</script>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
假设:CSS 会阻塞后面的 JS 运行,在 link 后面的 js 代码,应该要在 CSS 加载完成后才会输出
经过运行我们发现,位于 CSS 加载前的 JS 先执行,位于 CSS 后面的 JS 等到 CSS 加载完后 才执行,并且经过了 169ms 才执行。我们得出结论: CSS 会阻塞后面 JS 的执行
# 原理解析
浏览器的渲染机制一般分为以下几个步骤:
- 处理 HTML 并构建 DOM 树 🌲
- 处理 CSS 构建 CSSOM 树 🌲
- 将 DOM 和 CSSOM 合并成一个渲染树 🌲
- 根据渲染树来布局,计算每个节点的位置
- 调用 GPU 绘制,合成图层,显示在屏幕

从图解可以看出
- DOM 解析和 CSS 解析是两个并行的进程,它们分别由不同的解析引擎去分析,这也解释了为什么 CSS 加载不会阻塞 DOM 的解析。
- 由于 Render Tree 是依赖于 DOM Tree 和 CSSOM Tree 的,所以他必须等待到 CSSOM Tree 构建完成,也就是 CSS 资源加载完成(或者 CSS 资源加载失败)后,才能开始渲染。因此,CSS 加载是会阻塞 Dom 的渲染的
- 由于 js 可能会操作之前的 Dom 节点和 css 样式,因此浏览器会维持 html 中 css 和 js 的顺序。因此,样式表会在后面的 js 执行前先加载执行完毕。所以 css 会阻塞后面 js 的执行。
# 结论
- CSS 加载 不会阻塞 DOM 🌲 的解析
- CSS 加载 会阻塞 DOM 🌲 的渲染
- CSS 加载 会阻塞 后面 JS 语句的执行
- CSS 下面没有 JS 时 不会阻塞 DOM Ready
- CSS 下面有 JS 时 会影响 DOM Ready