浏览器--JS和CSS对页面的阻塞

154 阅读1分钟

浏览器在构建页面时会并行处理 DOM 和 CSS,之后将 DOM 树和 CSSOM 树组合成 Render 树,遍历 Render 树布局和绘制元素:

  • 调用 HTML 解析器解析 HTML 构建 DOM 树;

  • 调用 CSS 解析器解析 CSS 构建 CSSOM 树;

  • 前两步解析过程并行执行,DOM 树和 CSSOM 树组合成 Render 树,再之后用 Render 树渲染、布局、绘制。

JS 文件在加载时会造成阻塞。HTML 解析器在 DOM 解析过程中遇到 JS 会停止解析,转而去加载并执行 JS,JS 执行完成后再继续解析 DOM。

原因: 历史遗留问题,早期的 JS 大量使用 document.write 方法,如果等 DOM 解析完再执行 JS,会造成大范围的回流,对性能影响太大。

如何避免:

  1. 使用 <script> 引用 JS 文件可以附带 defer 属性,该属性使 JS 文件在 DOM 解析时并行下载,DOM 解析完成之后再执行。

  2. <script> 标签放在闭合的 </body> 标签之前,使 HTML 解析器遇到 JS 时已解析完 DOM。

CSS 文件的引入位置决定其是否会造成阻塞,分多种情况:

  1. CSS 不会阻塞 DOM 解析,因为 HTML 解析器构建 DOM 树和 CSS 解析器构建 CSSOM 树是并行的。

  2. CSS 会阻塞 DOM 渲染,因为 DOM 渲染需要 DOM 树和 CSSOM 树组合成 Render 树,有 Render 树之后才开始渲染。

  3. CSS 会阻塞 JS 执行,因为 JS 可能会改变 CSS 中的内容,所以在 CSS 之后的 JS 会等待 CSS 加载完再执行。