面試的時候被問到一個問題:js會不會阻塞瀏覽器渲染?css會不會阻塞瀏覽器渲染? 在網上也查了不少資料,現在自己總結下。
總結
總結一句話:js是全阻塞,css會阻塞js的執行,先丟擲幾條規則,然後再貼測試程式碼
- JS 會阻塞後續 DOM 的解析和其它資源(如 CSS,JS 或圖片資源)的載入。
- css載入不會阻塞DOM樹的解析,不會阻塞其它資源(如圖片)的載入,CSS載入會阻塞DOM樹的渲染,也會阻塞 JS 檔案的執行。
新建一個index.js,用node啟動一個簡單的web server,訪問地址就是:http://127.0.0.1:9000/,
index.js
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.js
document.body.style.cssText = "background: blue !important"
複製程式碼
red.css
body {
background:red !important;
}
複製程式碼
green.css
body {
background: green !important;
}
複製程式碼
這裡說明下:yellow.js 和 blue.js 下載時間分別為 5s 和 10s,red.css 和 green.css 下載時間分別為 15s 和 20s。測試瀏覽器為谷歌劉瀏覽器,版本 70.0.3538.102(正式版本)(64 位)
來看看規則1:JS 會阻塞後續 DOM 的解析和其它資源(如 CSS,JS 或圖片資源)的載入。上截圖:
開啟到5秒前的瀏覽器效果
開啟瀏覽器,yellow.js是5秒後下載完畢,此時js會阻塞後續 DOM 的解析和其它資源(如 CSS,JS 或圖片資源)的載入。所以此時瀏覽器只會顯示文字“第一行內容”。開啟到5秒左右的瀏覽器效果
此時yellow.js下載完成執行,瀏覽器的背景顏色就是yellow了。開啟到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 樣式都被劃掉了)