Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

3.2 优化 CRP(一) Optimize Critical Rendering Path I #159

Open
EthanLin-TWer opened this issue Mar 31, 2017 · 0 comments
Open

3.2 优化 CRP(一) Optimize Critical Rendering Path I #159

EthanLin-TWer opened this issue Mar 31, 2017 · 0 comments
Assignees

Comments

@EthanLin-TWer
Copy link
Owner

EthanLin-TWer commented Mar 31, 2017

CRP 优化

CRP 的五个步骤:构造 DOM、构造 CSSOM、构造渲染树、计算布局、绘制屏幕。本篇讲了前两个的优化,以及如何计算 CRP 的数量来获得网页性能的一般感觉。这篇文章中谈到,优化 CRP,主要是优化这三个指标:

  • The number of critical resources.
  • The critical path length.
  • The number of critical bytes.

总的优化建议及次序是:

  1. Analyze and characterize your critical path: number of resources, bytes, length 分析、画出关键路径资源现况:资源数量、大小
  2. Minimize number of critical resources: eliminate them, defer their download, mark them as async, and so on 最小化关键资源的数量:移除非绝对必要的资源、推迟下载、异步下载等
  3. Optimize the number of critical bytes to reduce the download time (number of roundtrips) 优化关键资源的大小,减少下载时间(及 RTT 数)
  4. 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)

image

HTML 的优化

DOM 树的构造必须等到 CSSOM 构建完成及所有会阻塞 HTML 加载的 JS 运行完才能完成,因而渲染树也会等到此时才可能进行生成。因此,HTML 部分的优化建议有:

  • minify HTML、减少网络传输的字节数。比如干掉全部空格、注释等
  • compress HTML using GZip
  • 缓存

CSS 的优化

CSSOM 的构造是渲染树生成的重要部分。因此,加速 CSS 这个部分也是 CRP 路径优化中的重要一步。由于 CSS 可被覆盖的特性,决定了它是渲染阻塞型 render blocking 的资源,浏览器必须接受到所有 CSS 后开始构建渲染才有意义。另外,一般 CSS 是作为外部文件引用被引入(又比如网络字体等),此时也必然会发生网络下载。所以,CSS 优化主要从 下载CSSOM 构造 两个方面来入手:不是必要的资源全部干掉不下载、必须下载的资源尽量减少数量和传输大小。

  • 对于可能干掉的请求,直接干掉不让「下载」发生,如:
  • 对于不能干掉但渲染不紧急的资源:通过 media 属性 异步下载和加载之
  • 对于不能干掉且渲染紧急的资源:
    • 减少 CSS 数量:合并同类 css 文件。何谓同类?比如页面渲染无论如何所必须的 CSS、打印时需要的 CSS、特定分辨率下的 CSS 等
    • 减少传输的 CSS 文件大小:
      • minify
      • purify: 移除根本就没用到的 CSS 代码,比如框架代码等
      • compress:GZip
    • 尽快下载 critical CSS 文件

把 CSS 置于页面底部。这样它不会阻塞 HTML 树的 parse 过程,并利用这段时间进行下载、加载

上面这个说法是错误的,而且应该相反。默认情况下,CSS 是渲染阻塞型的资源,也即浏览器必须等到 CSS 下载完毕、加载完成以后,才可能完成第一次渲染(因为需要下载完成后才能构造 CSSOM,CSSOM 构造完成才能构造渲染树)。因此,上面这个说法,在浏览器没有类似 pre-loader 等优化时,只会拖后腿,不会加快性能。

JS 优化

image

image

JS 和 HTML 及 CSS 的关系就更有趣了。由于 JS 既可以修改 CSS 属性,又可以通过 DOM API 修改 DOM 结构,所以一般:js 会在 css 加载完后再执行,并且js 执行完毕之后 DOM 的构造才最终确定下来。所以 JS 这一环的速度同样关键,主要优化思路和 CSS 部分相同:

  • 对于可能干掉的请求,直接干掉不让「下载」发生,如:
    • 浏览器缓存
    • inline 小型的 JS
  • 对于不能干掉但渲染不紧急的资源:通过 asyncdefer 属性 异步下载和加载之。比如 analytics, performance 文件等
  • 对于不能干掉且渲染紧急的资源:
    • 减少 JS 数量:合并同类 js 文件。比如项目文件一类 bundle.js,外部依赖一类 vendor.js
    • 减少传输的 JS 文件大小:
      • minify
      • purify: 移除根本就没有被调用的 JS 代码,当然这个在源代码级别也必须经常清理,但 purify 也适用于移除框架代码
      • uglify
      • compress:GZip

image

上左,由于 JS 必须等到 CSS 加载完成后再执行,因此,若 JS 的执行发生在 CSS 加载之前,必然是通过 async 方式异步加载了 JS;上中,因为没有发生 JS 文件的下载,所以 JS 必然是被 inline 进去了;上右,由于发生了 JS 的下载并且其下载完成于 CSS 先,但执行发生于 CSS 后,所以是一般的 blocking 加载方式。

感受一个一般的更复杂的网页 CRP:

image

总结

优化虽然是个复杂的工程,但简单点来说,要提高网页加载「速度」,无非是两个思路:

  • 减少请求文件总体积
  • 加快加载渲染时间

加载渲染时间主要和 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 。看看这个网站有没有命令行版本。

image

GZip 工作的基础是以更高效的编码方式压缩重复字符串,它使用于 HTML/CSS/JS 等文本文件的基础上是,它们有很多重复的字符串,这样 GZip 可以达到很高的压缩效率。它们之所以能达到很高的重复率,本质上是因为它们是一门编程/标记语言。下图是几种不同的压缩算法,可以看到在加解密时间及产出的压缩效率上,GZip 的效率是相对最高的。看 这里

image

不过要知道,GZip 不是银弹,如果被压缩文本重复率极低(不是编程语言通常会产生这种情况),或者被压缩文本已经被其他算法处理过了(因而重复率极低),使用 GZip 可能反而会增加文件的体积,因为需要更多的冗余编码信息。当然,一般很少出现这种事情,不过还是要留意一下。

image

image

最佳实践

思路 优化方法 HTML CSS JS image
消灭请求 缓存
inline 小型资源
减少请求 合并 critical 资源
异步非阻塞加载非 critical 资源
最小化请求文件 minify
purify
uglify
compress

以上过程宜采用自动化工具,在构建的时候完成,生成 prod 文件部署到生产环境,而不需要在开发者本地进行。当然如果进行不需成本,那当然好。

Best Materials

Other Recommendations

@EthanLin-TWer EthanLin-TWer added this to the Iteration 4: Husky🐶 milestone Mar 31, 2017
@EthanLin-TWer EthanLin-TWer self-assigned this Mar 31, 2017
@EthanLin-TWer EthanLin-TWer changed the title 3.2 优化 CRP Optimize Critical Rendering Path 3.2 优化 CRP(一) Optimize Critical Rendering Path I Apr 5, 2017
@EthanLin-TWer EthanLin-TWer reopened this Aug 19, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant