CSS 阻塞
CSS 是阻塞渲染的资源。需要将它尽早、尽快下载到客户端,以便缩短首次渲染的时间。
浏览器在构建 CSSOM 的过程中,不会渲染任何已处理的内容。即使 DOM 已经解析完毕,只要 CSSOM 还没有解析完成,那么渲染树就不能构建成功。
优化建议:
- 将 CSS 放在 head 标签里
- 启用 CDN 优化静态资源加载速度
JS 阻塞
阻塞 DOM 和 CSSOM
JS 的作用:修改页面的内容、样式以及响应用户交互。本质上是对 DOM 和 CSSOM 进行修改,因此在不显式声明的情况下,JS 的执行会阻塞 DOM 和 CSSOM。
原因:JS 引擎是独立于渲染引擎存在的。我们的 JS 代码在文档的何处插入,就在何处执行。当 HTML 解析器遇到一个 script 标签时,它会暂停渲染过程,将控制权交给 JS 引擎。JS 引擎对内联的 JS 代码会直接执行,对外部 JS 文件还要先获取到脚本、再进行执行。等 JS 引擎运行完毕,浏览器又会把控制权还给渲染引擎,继续 CSSOM 和 DOM 的构建。 因此与其说是 JS 把 CSS 和 HTML 阻塞了,不如说是 JS 引擎抢走了渲染引擎的控制权。
优化建议:
合理使用外部 JS 的三种加载方式。作为开发者当我们可以确认一个 JS 文件的执行时机时,我们可以通过合理使用 defer 和 async 来避免不必要的阻塞。
从应用的角度来说,一般当我们的脚本与 DOM 元素和其它脚本之间的依赖关系不强时,我们会选用 async;当脚本依赖于 DOM 元素和其它脚本的执行结果时,我们会选用 defer。
JS的三种加载方式:
- 正常模式:
这种情况下 JS 会阻塞浏览器,浏览器必须等待 index.js 加载和执行完毕才能去做其它事情。 - async 模式:
async 模式下,JS 不会阻塞浏览器做任何其它的事情。它的加载是异步的,当它加载结束,JS 脚本会立即执行。 - defer 模式:
defer 模式下,JS 的加载是异步的,执行是被推迟的。等整个文档解析完成、DOMContentLoaded 事件即将被触发时,被标记了 defer 的 JS 文件才会开始依次执行。