1. DOMContentLoaded 与 load 的区别 ?
当 DOMContentLoaded 事件触发时,仅当 DOM 解析完成后,不包括样式表,图片。我们前面提到CSS 加载会阻塞 Dom 的渲染和后面 js 的执行,js 会阻塞 Dom 解析,所以我们可以得到结论:
当文档中没有脚本时,浏览器解析完文档便能触发 DOMContentLoaded 事件。如果文档中包含脚本,则脚本会阻塞文档的解析,而脚本需要等 CSSOM 构建完成才能执行。在任何情况下,DOMContentLoaded 的触发不需要等待图片等其他资源加载完成。
当 onload 事件触发时,页面上所有的 DOM,样式表,脚本,图片等资源已经加载完毕。
DOMContentLoaded -> load。
2. 什么是CRP,即关键渲染路径(Critical Rendering Path)? 如何优化?
关键渲染路径是浏览器将 HTML CSS JavaScript 转换为在屏幕上呈现的像素内容所经历的一系列步骤。也就是我们上面说的浏览器渲染流程。
为尽快完成首次渲染,我们需要最大限度减小以下三种可变因素:
关键资源的数量: 可能阻止网页首次渲染的资源。
关键路径长度: 获取所有关键资源所需的往返次数或总时间。
关键字节: 实现网页首次渲染所需的总字节数,等同于所有关键资源传送文件大小的总和。
1. 优化 DOM
删除不必要的代码和注释包括空格,尽量做到最小化文件。
可以利用 GZIP 压缩文件。
结合 HTTP 缓存文件。
2. 优化 CSSOM
缩小、压缩以及缓存同样重要,对于CSSOM我们前面重点提过了它会阻止页面呈现,因此我们可以从这方面考虑去优化。
减少关键 CSS 元素数量
当我们声明样式表时,请密切关注媒体查询的类型,它们极大地影响了 CRP 的性能 。
3. 优化 JavaScript
当浏览器遇到 script 标记时,会阻止解析器继续操作,直到 CSSOM 构建完毕,JavaScript 才会运行并继续完成 DOM 构建过程。
async: 当我们在 script 标记添加 async 属性以后,浏览器遇到这个 script 标记时会继续解析 DOM,同时脚本也不会被 CSSOM 阻止,即不会阻止 CRP。
defer: 与 async 的区别在于,脚本需要等到文档解析后( DOMContentLoaded 事件前)执行,而 async 允许脚本在文档解析时位于后台运行(两者下载的过程不会阻塞 DOM,但执行会)。
当我们的脚本不会修改 DOM 或 CSSOM 时,推荐使用 async 。
预加载 —— preload & prefetch 。
DNS 预解析 —— dns-prefetch 。
总结
分析并用关键资源数 关键字节数 关键路径长度来描述我们的 CRP 。
最小化关键资源数: 消除它们(内联)、推迟它们的下载(defer)或者使它们异步解析(async)等等 。
优化关键字节数(缩小、压缩)来减少下载时间 。
优化加载剩余关键资源的顺序: 让关键资源(CSS)尽早下载以减少 CRP 长度 。