前端每日一问--JS 和 CSS 阻塞问题

面试的时候被问到一个问题:js会不会阻塞浏览器渲染?css会不会阻塞浏览器渲染? 在网上也查了很多资料,如今本身总结下。css

总结

总结一句话:js是全阻塞,css会阻塞js的执行,先抛出几条规则,而后再贴测试代码html

  • JS 会阻塞后续 DOM 的解析和其它资源(如 CSS,JS 或图片资源)的加载。
  • css加载不会阻塞DOM树的解析,不会阻塞其它资源(如图片)的加载,CSS加载会阻塞DOM树的渲染,也会阻塞 JS 文件的执行。

新建一个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秒前的浏览器效果

打开浏览器,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 样式都被划掉了)

相关文章
相关标签/搜索