js阻塞dom的构建 && CSS通过js来阻塞DOM的构建 && async、defer

  • Post author:
  • Post category:其他




js阻塞dom的构建 && CSS通过js来阻塞DOM的构建

  • JavaScript脚本由于可能会修改DOM,因此会阻塞DOM的构建,这一点我们都知道;而CSS并不会操作或者改变DOM,因此通常我们认为CSS不会影响DOM的构建,只会影响后续的布局、绘制等过程,即会影响DOM的渲染。但其实CSS可以通过JavaScript来阻塞DOM的构建。

    因为JavaScript是可以改变样式的,也就是具有修改CSS规则树的能力,而JavaScript脚本里是否有改变样式的操作,这一点在执行JavaScript之前是不可知的。因此,为保证JavaScript脚本的正确执行,在执行JavaScript之前,CSS规则树必须要先准备好(不然万一有修改CSS的操作呢)。

    也就是说,若在构建DOM的中途存在阻塞DOM构建的JavaScript脚本,而此页面中还包含了外部 CSS 文件的引用,那么此时就需要等目前的CSS规则树(基于目前生成完的部分DOM树)构建完毕后,再开始JavaScript脚本的执行,等一切结束了,再继续DOM的构建。

  • UI线程与JS线程是互斥的,因为JS运行结果会影响到UI线程的结果,当JS线程运行的时候,UI线程处于冻结状态。(现在浏览器可能对某些事件做了特殊处理,比如监听了scroll事件,在滚动时还是能够流畅的播放动画)。



DOM与CSS

  • 没有js的理想情况下,html与css会并行解析,分别生成DOM与CSSOM
  1. css的加载不会阻塞DOM的解析(能通过js阻塞)
  2. css的加载会阻塞DOM的渲染



DOM与JS

  1. JS的加载和执行会阻塞DOM的解析
  2. JS的加载和执行会阻塞DOM的渲染



异步加载JavaScript脚本

<script src="path/to/myModule.js" defer></script>
<script src="path/to/myModule.js" async></script>
 <!-- defer是“页面DOM解析完再执行”,async是“js脚本下载完就执行” -->
  • 相同点:
  1. 都只使用于外部脚本
  2. 都会立即异步下载js文件
  3. 都有兼容性的问题
  • 不同点:
  1. defer在DOM解析完成之后在DOMContentLs:oaded之前执行脚本,且按照script标签出现的顺序执行(有些版本的浏览器不会顺序执行),因此,defer适合于与dom有关的脚本,也适用于执行有先后依赖的脚本
  2. async是在脚本下载完成之后立即执行,所以脚本执行的先后顺序不一定(谁先下载完谁先执行),也有可能会阻塞DOM的解析。因此,async适合第三方脚本,不操作dom
  • tips:如果考虑兼容,最好是把script标签放在body的最后



浏览器加载ES6模块

  • 使用type = ‘module’
  • 属于异步加载,等同于打开了defer属性
<script type="module" src="./foo.js"></script>



补充DOMContentLoaded和load的调用时机:

1,解析HTML结构。

2,DOM树构建完成。//DOMContentLoaded

3,加载外部脚本和样式表文件。

4,解析并执行脚本代码。

5,加载图片等外部文件。

6,页面加载完毕。//load

在第2步,会触发DOMContentLoaded事件。在第6步,触发load事件。



版权声明:本文为qq_36303110原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。