3.2 优化 CRP(一) Optimize Critical Rendering Path I
CRP 优化
CRP 的五个步骤:构造 DOM、构造 CSSOM、构造渲染树、计算布局、绘制屏幕。本篇讲了前两个的优化,以及如何计算 CRP 的数量来获得网页性能的一般感觉。这篇文章中谈到,优化 CRP,主要是优化这三个指标:
- The number of critical resources.
- The critical path length.
- The number of critical bytes.
总的优化建议及次序是:
- Analyze and characterize your critical path: number of resources, bytes, length 分析、画出关键路径资源现况:资源数量、大小
- Minimize number of critical resources: eliminate them, defer their download, mark them as async, and so on 最小化关键资源的数量:移除非绝对必要的资源、推迟下载、异步下载等
- Optimize the number of critical bytes to reduce the download time (number of roundtrips) 优化关键资源的大小,减少下载时间(及 RTT 数)
- Optimize the order in which the remaining critical resources are loaded: download all critical assets as early as possible to shorten the critical path length 对于那些已优化的、必须的关键资源,优化它们的加载次序:尽快下载所有关键资源,以缩短关键路径长度(critical path length)
HTML 的优化
DOM 树的构造必须等到 CSSOM 构建完成及所有会阻塞 HTML 加载的 JS 运行完才能完成,因而渲染树也会等到此时才可能进行生成。因此,HTML 部分的优化建议有:
- minify HTML、减少网络传输的字节数。比如干掉全部空格、注释等
- compress HTML using GZip
- 缓存
CSS 的优化
CSSOM 的构造是渲染树生成的重要部分。因此,加速 CSS 这个部分也是 CRP 路径优化中的重要一步。由于 CSS 可被覆盖的特性,决定了它是渲染阻塞型 render blocking 的资源,浏览器必须接受到所有 CSS 后开始构建渲染才有意义。另外,一般 CSS 是作为外部文件引用被引入(又比如网络字体等),此时也必然会发生网络下载。所以,CSS 优化主要从 下载 和 CSSOM 构造 两个方面来入手:不是必要的资源全部干掉不下载、必须下载的资源尽量减少数量和传输大小。
- 对于可能干掉的请求,直接干掉不让「下载」发生,如:
- 浏览器缓存
- inline 小型的 CSS https://github.com/addyosmani/critical
- 对于不能干掉但渲染不紧急的资源:通过
media
属性 异步下载和加载之 - 对于不能干掉且渲染紧急的资源:
- 减少 CSS 数量:合并同类 css 文件。何谓同类?比如页面渲染无论如何所必须的 CSS、打印时需要的 CSS、特定分辨率下的 CSS 等
- 减少传输的 CSS 文件大小:
- minify
- purify: 移除根本就没用到的 CSS 代码,比如框架代码等
- compress:GZip
- 尽快下载 critical CSS 文件
把 CSS 置于页面底部。这样它不会阻塞 HTML 树的 parse 过程,并利用这段时间进行下载、加载
上面这个说法是错误的,而且应该相反。默认情况下,CSS 是渲染阻塞型的资源,也即浏览器必须等到 CSS 下载完毕、加载完成以后,才可能完成第一次渲染(因为需要下载完成后才能构造 CSSOM,CSSOM 构造完成才能构造渲染树)。因此,上面这个说法,在浏览器没有类似 pre-loader 等优化时,只会拖后腿,不会加快性能。
- https://developers.google.com/web/fundamentals/performance/critical-rendering-path/render-blocking-css
- https://developers.google.com/speed/docs/insights/OptimizeCSSDelivery
JS 优化
JS 和 HTML 及 CSS 的关系就更有趣了。由于 JS 既可以修改 CSS 属性,又可以通过 DOM API 修改 DOM 结构,所以一般:js 会在 css 加载完后再执行,并且js 执行完毕之后 DOM 的构造才最终确定下来。所以 JS 这一环的速度同样关键,主要优化思路和 CSS 部分相同:
- 对于可能干掉的请求,直接干掉不让「下载」发生,如:
- 浏览器缓存
- inline 小型的 JS
- 对于不能干掉但渲染不紧急的资源:通过
async
或defer
属性 异步下载和加载之。比如 analytics, performance 文件等 - 对于不能干掉且渲染紧急的资源:
- 减少 JS 数量:合并同类 js 文件。比如项目文件一类
bundle.js
,外部依赖一类vendor.js
- 减少传输的 JS 文件大小:
- minify
- purify: 移除根本就没有被调用的 JS 代码,当然这个在源代码级别也必须经常清理,但 purify 也适用于移除框架代码
- uglify
- compress:GZip
- 减少 JS 数量:合并同类 js 文件。比如项目文件一类
上左,由于 JS 必须等到 CSS 加载完成后再执行,因此,若 JS 的执行发生在 CSS 加载之前,必然是通过 async
方式异步加载了 JS;上中,因为没有发生 JS 文件的下载,所以 JS 必然是被 inline 进去了;上右,由于发生了 JS 的下载并且其下载完成于 CSS 先,但执行发生于 CSS 后,所以是一般的 blocking 加载方式。
感受一个一般的更复杂的网页 CRP:
总结
优化虽然是个复杂的工程,但简单点来说,要提高网页加载「速度」,无非是两个思路:
- 减少请求文件总体积
- 加快加载渲染时间
加载渲染时间主要和 JS、CSS 写法有关系,比较复杂,后面再深入;
减少请求文件总体积,主要两个思路:对于可能干掉的请求直接消灭,对于必须的请求尽量减少传输的文件数量和文件大小
- 直接消灭请求
- 缓存
- inline 必要但小型的 JS 或 CSS
- 无法消灭的请求
- 减少请求数量
- 绝对必要的文件:尽量合并同类文件,这就要求良好的模块化划分和编写技巧
- 非绝对必要的文件:延迟加载,或异步非阻塞下载
- 减少文件体积
- minify:去除空格、注释等,适用于 HTML、CSS
- purify:移除写了但并没有用到的代码,适用于 CSS、JS
- uglify:缩短变量名等,使用 JS
- compress:从编码角度进一步压缩,使用于 HTML、CSS、JS
- 减少请求数量
压缩,压的是特定文件的解码信息。一段存储了信息的文本,除了存储其本身的内容外,还存储了用于解释其含义的“元数据”,俗称解码信息,它是与特定文件类型相关的上下文信息。针对特定类型的文件,如果能有表达效率更高的编码方式,使其与原来编码含义相同,那么 就可以在传输信息不变的情况下,压缩内容长度,提升编码效率。GZip 就是对于 HTML、CSS、JS 这类文本文件的最佳优化方案,平均可以达到 60%~80% 的压缩率。
这里可以检测你的网站是否开启了 GZip:https://checkgzipcompression.com 。看看这个网站有没有命令行版本。
GZip 工作的基础是以更高效的编码方式压缩重复字符串,它使用于 HTML/CSS/JS 等文本文件的基础上是,它们有很多重复的字符串,这样 GZip 可以达到很高的压缩效率。它们之所以能达到很高的重复率,本质上是因为它们是一门编程/标记语言。下图是几种不同的压缩算法,可以看到在加解密时间及产出的压缩效率上,GZip 的效率是相对最高的。看 这里。
不过要知道,GZip 不是银弹,如果被压缩文本重复率极低(不是编程语言通常会产生这种情况),或者被压缩文本已经被其他算法处理过了(因而重复率极低),使用 GZip 可能反而会增加文件的体积,因为需要更多的冗余编码信息。当然,一般很少出现这种事情,不过还是要留意一下。
最佳实践
思路 | 优化方法 | HTML | CSS | JS | image |
---|---|---|---|---|---|
消灭请求 | 缓存 | √ | √ | √ | |
inline 小型资源 | √ | √ | |||
减少请求 | 合并 critical 资源 | √ | √ | ||
异步非阻塞加载非 critical 资源 | √ | √ | |||
最小化请求文件 | minify | √ | √ | √ | |
purify | √ | √ | |||
uglify | √ | ||||
compress | √ | √ | √ |
以上过程宜采用自动化工具,在构建的时候完成,生成 prod 文件部署到生产环境,而不需要在开发者本地进行。当然如果进行不需成本,那当然好。
Best Materials
- Analyzing Critical Rendering Path
- Optimize Content Efficiency
- Render Blocking CSS
- High Performance Browser Networking
Other Recommendations
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论