面试的时候被问到一个问题:js会不会阻塞浏览器渲染?css会不会阻塞浏览器渲染? 在网上也查了很多资料,如今本身总结下。css
总结一句话:js是全阻塞,css会阻塞js的执行,先抛出几条规则,而后再贴测试代码html
新建一个index.js,用node启动一个简单的web server,访问地址就是:http://127.0.0.1:9000/,node
index.jsweb
const http = require('http')
const fs = require('fs')
const hostname = '127.0.0.1'
const port = 9000
http.createServer((req, res) => {
if(req.url === "/") {
fs.readFile("index.html", "utf-8", function(err, data) {
res.writeHead(200, { 'Content-Type': 'text/html' })
res.write(data)
res.end()
})
} else if (req.url === "/yellow.js") {
//延迟 5s
fs.readFile("yellow.js", "utf-8", function(err, data) {
res.writeHead(200, { 'Content-Type': 'text/plain' })
setTimeout(function () {
res.write(data)
res.end()
}, 5000)
})
} else if (req.url === "/blue.js") {
//延迟 10s
fs.readFile("blue.js", "utf-8", function(err, data) {
res.writeHead(200, { 'Content-Type': 'text/plain' })
setTimeout(function () {
res.write(data)
res.end()
}, 10000)
})
} else if (req.url === "/red.css") {
//延迟 15s
fs.readFile("red.css", "utf-8", function(err, data) {
res.writeHead(200, { 'Content-Type': 'text/css' })
setTimeout(function () {
res.write(data)
res.end()
}, 15000)
})
} else if (req.url === "/green.css") {
//延迟 20s
fs.readFile("green.css", "utf-8", function(err, data) {
res.writeHead(200, { 'Content-Type': 'text/css' })
setTimeout(function () {
res.write(data)
res.end()
}, 20000)
})
}
}).listen(port, hostname, () => {
console.log('the Server running at ' + hostname)
})
复制代码
index.html面试
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="cache-control" content="no-cache,no-store, must-revalidate" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>测试浏览器渲染</title>
</head>
<body>
<p>第一行内容</p>
<script src="/yellow.js"></script>
<p>第二行内容</p>
<link rel="stylesheet" href="/red.css">
<p>第三行内容</p>
<script src="/blue.js"></script>
<p>第四行内容</p>
<link rel="stylesheet" href="/green.css">
<img src="http://www.quanjing.com/image/2018image/homepage/3.jpg?v=8">
<p>第五行内容</p>
</body>
</html>
复制代码
yellow.js浏览器
document.body.style.cssText = "background: yellow !important"
复制代码
blue.jsbash
document.body.style.cssText = "background: blue !important"
复制代码
red.css测试
body {
background:red !important;
}
复制代码
green.cssui
body {
background: green !important;
}
复制代码
这里说明下:yellow.js 和 blue.js 下载时间分别为 5s 和 10s,red.css 和 green.css 下载时间分别为 15s 和 20s。测试浏览器为谷歌刘浏览器,版本 70.0.3538.102(正式版本)(64 位)url
来看看规则1:JS 会阻塞后续 DOM 的解析和其它资源(如 CSS,JS 或图片资源)的加载。上截图:
打开到5秒前的浏览器效果
打开到5秒左右的浏览器效果
打开到5秒后到15秒左右的浏览器效果
red.css是15秒左右下载完成,而blue.js是10秒左右下载完成,在浏览器中咱们看到是这样的效果:blue.js比red.css先下载完成,可是blue.js并无执行,等red.css加载完成后blue.js才会执行。这就符合了前面的规则二:css加载不会阻塞DOM树的解析,不会阻塞其它资源(如图片)的加载,CSS加载会阻塞DOM树的渲染,也会阻塞 JS 文件的执行。
最后浏览器效果:
等green.css加载完毕后图片才会显示出来,也能说明CSS加载会阻塞DOM树的渲染,可是不会阻塞DOM树的解析
最后这里说明下为何最后 body 的背景色没有变成绿色:由于 js 定义的样式在内联样式,优先级高于在 CSS 文件中定义的样式,因此不是 green.css 没有加载,而是没有生效。看下图就知道了:(green 和 red 样式都被划掉了)