JS 阻塞与 CSS 阻塞

447 阅读2分钟

页面渲染过程

首先我们知道,从 0 开始到页面完全加载,会经历如下过程:

  1. 解析 HTML,生成 DOM 树
  2. 解析 CSS,生成 CSS 树
  3. 合并以上得到渲染树
  4. 根据渲染树得到元素的几何信息,进行布局
  5. 注入元素的其他属性,比如颜色,进行绘制
  6. GPU 线程得到以上信息,将各层合成,展现到屏幕上

JS 阻塞

由于 GUI 渲染线程和 JS 引擎线程是互斥的,所以如果存在大量的 JS 操作,那么页面的渲染就要排队,否则在未知的 JS 代码中,可能要修改样式,为了避免重复的回流与重绘,浏览器有意而为之

所以 onload 事件触发延后于 DOMContentLoaded 事件,因为后者只要在 DOM 解析后就会触发

CSS 阻塞

虽然 CSS 文件是由单独的下载线程异步下载的,但是在合成渲染树时需要 CSS 树,所以过久的 CSS 解析会阻碍渲染树的渲染

所以想要优化,就要异步加载 JS,还有优化样式表的加载

优化

具有 async 属性的 Script,表示脚本的加载和文档的解析并行,但是脚本的执行会阻塞后续文档的解析,但是如果在脚本加载完之前,文档的解析结束,那么将不会产生阻塞,但是大多数时候都不会这样

具有 defer 属性的 Script,表示脚本的加载和文档的解析并行,但是脚本的执行在文档完全加载之后执行,所以尽量多使用 defer 属性

可以使用媒体查询来分割大型 CSS 文件,让其按需加载,提高加载速度,也可以使用打包工具对文件进行压缩,合理使用缓存