前言
前面有分析过页面的渲染逻辑(老生常谈之从输入URL到页面呈现的过程(全)),从上至下解析 HTML,构建 DOM 树和 Style Rules,其中构建 DOM 和解析 Style 是并行的,之后 DOM 树和 Style Rules 结合成 Render Tree。
下面我们来分析分析 CSS 和 JS 对 HTML 解析(DOM,Style Rules,Render Tree)的阻塞性
运行以下 Demo 的时候需要将浏览器控制台的网络先设置为
Slow 3G
CSS 的阻塞性
- 不阻塞 DOM 树的解析,但会阻塞 Style Rules 的解析,进而阻塞 Render Tree (因为渲染树需要等待 Style Rules,减少不必要的回流重绘)
<!DOCTYPE html>
<html>
<head>
<script>
setTimeout(() => {
console.log(document.getElementById('app'))
})
</script>
<link href="https://cdn.bootcdn.net/ajax/libs/animate.css/4.1.1/animate.compat.css" rel="stylesheet">
</head>
<body>
<div id="app">
666
</div>
</body>
</html>
- 阻塞在 CSS 之后的 JS 的解析执行(因为某些 JS API 如 getComputedStyle 需要最新的样式数据)
<!DOCTYPE html>
<html>
<head>
<link href="https://cdn.bootcdn.net/ajax/libs/animate.css/4.1.1/animate.compat.css" rel="stylesheet">
<script>
console.log(1)
</script>
</head>
<body>
<div id="app">
666
</div>
</body>
</html>
JS 的阻塞性
- JS 会阻塞在
其后的 DOM 树的构建,进而影响 Render Tree。(因为 JS 经常操作 DOM API,为确保 DOM 一致性)。
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<div id="app1">
333
</div>
<script>
console.log(document.getElementById('app1'))
console.log(document.getElementById('app2'))
</script>
<script src="https://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.20/lodash.js"></script>
<div id="app2">
555
</div>
</body>
</html>
异步脚本的阻塞性
前面我们其实说的是同步脚本的阻塞性,下面来看看异步脚本的阻塞性
从网上找的这幅图描述的相当的一目了然
- script
立即下载执行,下载执行的过程中阻塞 HTML 解析(DOM 构建)
- async script
立即下载执行,但是下载过程不影响 HTML 解析(DOM 构建)(也就不影响渲染),仅在执行过程阻塞 HTML 解析(DOM 构建)
执行不按顺序
- defer script
立即下载,延迟执行(HTML 解析完成后),不阻塞 HTML 的解析(DOM 构建)((也就不影响渲染)
执行按顺序
总结
知道了 CSS 与 JS 的阻塞性及其阻塞背后的设计思想,有助于提升自己对页面渲染流程的认知,并且可以给页面的性能优化提供思路,知其然知其所以然,一起加油。
参考
欢迎来前端菜鸟群一起摸鱼划水~516913974