css阻塞dom解析么

众所周知,js的加载会阻塞dom解析, 那么css呢??整理一下知识点

二次更新:
推荐一篇文章,光看图片就能明白了,挺不错 https://hacks.mozilla.org/2017/09/building-the-dom-faster-speculative-parsing-async-defer-and-preload/

前言

先来一张图 HTML - DOM
HTML-DOM

我们在访问某一个网页时,浏览器是先请求 HTML, 然后才是外部资源,例如:js脚本,css样式,所以在顺序上是先构建的 DOM

例如常见的两个dom事件: onLoad, DOMContentLoaded , 这两个最大区别就在于触发的时机,load是包含了外部资源加载的时间,比如:图片、样式等等。DOMContentLoaded 是在dom数构建之后触发的。

外部资源不会影响 DOMContentLoaded 触发, 但是脚本会,默认情况下 js 是同步的,除非 加上 异步属性 deferasync 之后。

  • async 标志的脚本文件一旦加载完成就会立即执行,并且不会按照书写顺序,谁下载好了就直接执行。所以适用于那些没有代码依赖顺序,并且没有 DOM操作 的脚本文件。
  • defer 标志的脚本文件会严格按照书写顺序执行,并且,会在 DOMContentLoaded 事件之前(也就是页面DOM加载完成时)执行。适用于有 DOM操作 ,或者是有代码依赖顺序的脚本文件。

css 的阻塞

css 阻塞无非以下几种情况

  • 阻塞解析HTML
  • 阻塞渲染HTML
  • 不阻塞解析
  • 不阻塞渲染

不过,如果css 阻塞了解析,必然导致渲染会延迟。

我们可以通过开发者工具来验证一下,

  • 第一轮测试的 请求资源 4 是表示 js加载设置了4s延迟, 3是css,设置了3s延迟。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title></title>
    <script type="text/javascript" src="http://localhost:9800/api/file/js/4"></script>
    <link rel="stylesheet" type="text/css" href="http://localhost:9800/api/file/css/3">
    </head>
    <body>
    <h1 class="font">^_^</h1>
    <h2 class="font">😭</h2>

    <button id="reload">xxx</button>
    <button id="reload">ooo</button>
    </body>
    </html>

js 和 css 同时加载的下:
css

可以看到 js(4) 和css(3)是同时请求加载的, 解析html是在js加载之后,

只是加载css:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title></title>
<!-- <script type="text/javascript" src="http://localhost:9800/api/file/js/4"></script> -->
<link rel="stylesheet" type="text/css" href="http://localhost:9800/api/file/css/3">
</head>
<body>
<h1 class="font">^_^</h1>
<h2 class="font">😭</h2>

<button id="reload">xxx</button>
<button id="reload">ooo</button>
</body>
</html>

css

可以看到 css 的加载并未导致解析html停止。

证明: css是不会阻塞解析HTML的

  • 如果我在head里面的script 放在 link 之前呢,让 css 的加载时间延长到 5s, js 的加载时间缩短到 2s呢?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title></title>
    <link rel="stylesheet" type="text/css" href="http://localhost:9800/api/file/css/5">
    <script type="text/javascript" src="http://localhost:9800/api/file/js/2"></script>
    </head>
    <body>
    <h1 class="font">^_^</h1>
    <h2 class="font">😭</h2>

    <button id="reload">xxx</button>
    <button id="reload">ooo</button>
    </body>
    </html>
    css

怎么解析html 时间延后了,而且是在css加载之后,什么情况?怎么和上面的结论有出入啊?

那咱么去掉 js ,再来一次

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title></title>
<link rel="stylesheet" type="text/css" href="http://localhost:9800/api/file/css/5">
<!-- <script type="text/javascript" src="http://localhost:9800/api/file/js/2"></script> -->
</head>
<body>
<h1 class="font">^_^</h1>
<h2 class="font">😭</h2>

<button id="reload">xxx</button>
<button id="reload">ooo</button>
</body>
</html>

css

可以看到解析html时间又提前了,符合第一次测试的结果了,

可见:css 的阻塞其实和js 有关联的。

css 和 js 虽然可以同步加载,但是如果css是在js之前加载的,会导致js的阻塞,从而导致了 html的解析。

  • 把css 放在 body中再 试试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title></title>
</head>
<body>
<h1 class="font">^_^</h1>
<h2 class="font">😭</h2>

<link rel="stylesheet" type="text/css" href="http://localhost:9800/api/file/css/5">
<!-- <script type="text/javascript" src="http://localhost:9800/api/file/js/2"></script> -->
<button id="reload">xxx</button>
<button id="reload">ooo</button>
</body>
</html>

结果:

解析还是正常解析,并未被阻塞,但是 注意标红的地方(忽略之前的时间轴,那个是刷新之前的),按钮并未显示,而是等css 加载完成之后才展示的。 如果你在自己的浏览器重尝试的话,会明显感到按钮会闪现出来。

总结出来的几个点:

  • DOM 的解析是一个从上到下的过程
  • 所有外链资源浏览器都会已接近并发的情况来发起请求
  • CSS 会阻塞 渲染html,而且在某种情况下(后面有js的时候)还会阻塞解析,原因就是:浏览器不知道JS是否会需要查询 CSSDOM,所以需要等待CSS准备完毕。(来源于网络上的)

虽然js 、css 是近乎于同步的方式加载,但是针对 同一个域名 同时并发数量还是有限制的,数量基本上限制在 4-8 之间. 这也是你会看到大部分网站,图片、css、js有时候是分不同的域名。

注:以上测试截图环境均为: Chrome canary (x86_64) 105.0.5179.0(正式版本)

可能有不严谨的地方,欢迎大家指正

作者

Fat Dong

发布于

2022-07-14

更新于

2022-07-15

许可协议