前端优化--CSS&JS阻塞

190 阅读2分钟

CSS&JS阻塞

浏览器的渲染步骤

在了解JS&CSS阻塞前,我们需要知道浏览器渲染页面的步骤是什么?

  1. 浏览器根据HTML文件构建HTML树(DOM)
  2. 根据CSS文件构建CSS树(CSSOM)
  3. 将DOM和CSSOM合并成 render tree
  4. 计算Layout布局(文档流、盒模型、大小、位置)
  5. Paint绘制CSS的外观属性
  6. Compose合成,展示最终画面

CSS阻塞

CSS会阻塞页面的渲染

根据上面浏览器渲染页面的步骤,我们知道 render tree 的合成需要 DOM tree 和 CSSOM tree。所以CSS会阻塞页面的渲染,但是并不会阻塞DOM的解析,因为页面渲染 DOM tree 也是必须的。

当存在CSS阻塞的情况时,浏览器会延迟JavaScript的执行,但仍然会加载JavaScript的资源。

JS阻塞

JavaScript能够读取并修改 DOM 和 CSSOM 属性。

当浏览器在解析DOM时,如果遇到了一个<srcipt>标签,会停止DOM的构建,直至JavaScript文件执行完毕。

所以<srcipt>的位置显得尤为重要,错误的<srcipt>位置会导致严重的JS阻塞

解决方法

由于存在CSS阻塞的情况时,浏览器会延迟JavaScript的执行,同时JavaScript能够读取并修改 DOM 和 CSSOM 属性,所以我们要提高CSS资源的优先级

而且因为JavaScript的执行会停止DOM的构建,所以<srcipt>标签的位置最好在最后面

同时可以使用 <srcipt>标签的 defer async 属性来异步加载JavaScript文件。

defer & async

defer:延迟脚本

  1. 语法:<srcipt src='xxx' defer>
  2. defer必须使用在有src属性的<srcipt>标签上,即外联脚本
  3. 异步加载和解析JS文件
  4. defer的作用更像是把<srcipt>标签放到<body>标签的最后面。

async:异步脚本

  1. 语法:<srcipt src='xxx' async>
  2. async属性也只能作用于外联脚本。
  3. 异步加载JS文件,并在合适的时候执行,一定在window.load前执行。

defer V.S async

  1. 都是异步加载JS文件
  2. async脚本的执行会在渲染和绘制(DOMContentLoaded)之后开始执行和求值;而defer脚本执行之后才会执行DOMContentLoaded。