Hi,大家好我是 ssh,今天和大家分享一篇文章,讲述了 Chrome 团队和 Youtube 共同配合,优化了油管这个不存在的视频网站的性能。
- 首屏速度更快了
- 播放器组件大幅度优化
- 通过 Core Web Vitals 指标的页面比例更高
从这篇分享 Building a Better Web - Part 1: A faster YouTube on web[1]中,你能学习到世界上顶尖的团队是如何相互配合,优化世界各地用户的性能体验。
Chrome 团队经常谈到“建设更棒的 Web”,这啥意思呢?Web 体验应该快速[2]、可访问[3],并在用户最需要的时候具备网络可靠性[4]。
吃自己的狗食(Eating Your Own Dog Food)[5]是谷歌文化的一部分,所以 Chrome 团队与 YouTube 合作,在“建设更棒的 Web”的新系列中分享了在这个过程中学到的经验教训。这个系列的第一部分将深入探讨 YouTube 如何建立更迅捷的 Web 体验。
图片
PageSpeed Insights显示YouTube移动网页的Chrome用户体验报告数据通过了核心Web体验度量标准。
YouTube 移动观看页顺利超过Core Web Vitals[6]设立的阈值。
建设更快的 Web
对于 YouTube 来说,性能和网页上视频和其他内容(如推荐和评论)的加载速度有关。性能也由 YouTube 响应用户交互(如搜索、播放器控制、点赞和分享)的速度决定。
巴西、印度和印度尼西亚等发展中市场对 YouTube 移动网页很重要。由于这些地区的许多用户设备和网速都比较拉跨,确保快速流畅的体验就很关键了。
为了向所有用户提供良好的体验,YouTube 着手通过懒加载和代码现代化来改进Core Web Vitals[7]等性能指标。
改进 Core Web Vitals
为了判断需要改进哪些领域,YouTube 团队使用Chrome 用户体验报告(CrUX)[8]来查看移动端实际的用户在视频观看页面和搜索结果页面的体验,得知了他们的 Core Web Vitals 有很大的改进空间,在某些情况下,最大内容渲染时间(LCP)[9]指标达到 4-6 秒。这远高于他们 2.5 秒的目标。
图片
显示YouTube观看页面通过率以及YouTube源FCP和LCP图表
为了确定改进的细节,他们用Lighthouse[10]来审查 YouTube 观看页面,果然得到了一个较低的 Lighthouse(实验室[11])分数,首次内容渲染时间(FCP)为 3.5 秒,最大内容渲染时间(LCP) 为 8.5 秒。
YouTube移动网页的Lighthouse报告
Chrome 将 FCP 的目标设置为 1.8 秒,将 LCP 的目标设置为 2.5 秒作为黄金标准。FCP 和 LCP 分别为 3.5 秒和 8.5 秒,明显偏黄和偏红。
为了优化 FCP 和 LCP,YouTube 团队进行了几项实验,得到两个重大的发现。
- 第一个发现是,把视频播放器的 HTML 代码移动到视频播放相关的 JS 脚本之上,可以提高性能。实验室测试(Labs test)表明,这可以将 FCP 和 LCP 从 4.4 秒改善到 1.1 秒。
- 第二个发现是 LCP 只考虑[12]
<video>
元素的海报图,而不考虑视频流本身的帧。YouTube 一直在优化视频开始播放的最快时间,为了改进 LCP,团队开始优化他们可以交付海报图的速度。他们尝试了几种海报图的变体,并选择了在用户测试中得分最高的一种。作为这项工作的结果,FCP 和 LCP 都取得了显著改进,实际场景中的 LCP 从 4.6 秒提高到 2.0 秒。
图片
控制组、实验A(缩略图)和实验B(黑色缩略图)的移动网页观看页面LCP实验
在实验测试中,我们观察到这个更改落地后,FCP 和 LCP 从 4.4 秒提升到 1.1 秒。
- 实验 A:用实际的视频暂停截图作为海报图,用户表现不佳,导致用户活跃下降。
- 实验 B:使用实心黑色缩略图作为海报,结果很好,用户发现从实心黑色过渡到视频的第一帧,体验是很平稳的。
图片
2021年7月,黑色缩略图的方案部署成功,如上面的RUM分析所示,FCP和LCP有显著改进。
2021 年 7 月,黑色缩略图的方案部署成功,如上面的 RUM 分析所示,FCP 和 LCP 有显著改进。
在将这些优化引入所有平台的同时,YouTube 还利用了新的`fetchpriority`属性[13],我们将它与<link rel=preload>
一起使用,以优先发现和加载海报图:
<link as="image" rel="preload" href="poster.jpg" fetchpriority="high" />
虽然这些优化确实改进了 LCP,但团队觉得 LCP 指标的当前定义并没有完全捕获用户视角中的“主要内容”何时加载——这是 LCP 的目标。
为了解决这些问题,YouTube 团队的成员与 Chrome 团队的成员合作,探索改进 LCP 指标的方式,以解决他们的用例。在考虑了几个选项的可行性和影响后,两支团队得出的建议[14]是将视频元素的第一帧的绘制时间视为 LCP 候选项。
一旦这个变化在 Chrome 中落地,YouTube 团队就能开心的继续优化 LCP 了。这个指标更加接近用户真实的体验。
模块化与懒加载
YouTube 页面包含许多直接加载的模块。为了优化 50 多个组件的渲染方式,团队建立了一个组件到 JS 模块的 map,这个 map 将告诉客户端加载哪些模块。通过将组件标记为懒加载,JS 模块会晚一些加载,从而减少页面的初始加载时间和未使用 Javascript 的数量。
然而,在实现懒加载后,团队注意到懒加载的组件及其依赖项会在次优级时间批量加载。
为了解决这个问题,团队确定了视图中所需的最小组件集,并将它们打包在一个 Web 请求中。结果是页面速度得到改善,JavaScript 解析时间减少,最终得到了更好的初始渲染时间。
跨组件状态管理
YouTube 由于其播放器控件而遇到性能问题,特别是在较旧的设备上。代码分析显示,播放器(允许用户控制播放速度、进度等功能)随着时间的推移变得过度组件化了。
YouTube播放器和控件可视化
YouTube 视频播放器允许用户控制播放速度、跟踪进度、跳过部分等。当用户点击特定控件时,状态变化必须传达给其他控件,例如,用户点击进度条必须与播放头部、字幕等控件共享。
实验性能测试运行中,每次触摸移动进度条事件会额外触发两次样式重绘,花费 21.17 毫秒。随着时间推移添加新控件,去中心化控制的模式通常会导致循环依赖和内存泄漏,对观看页面性能产生负面影响。
性能时间轴上显示这个事件花了21.17毫秒
Chrome 开发者工具以 4 倍 CPU 减速运行性能。
为了解决去中心化控制带来的问题,团队更新了播放器 UI 来同步所有更新,实际上是把播放器重构成一个顶层组件,它会向子组件传递数据。这确保任何状态更改只有一次 UI 更新(渲染)周期,消除了链式更新。新的播放器进度条触摸移动事件,在其 JavaScript 执行期间不会带来样式重绘,现在只需要花费旧播放器 1/4 的时间。
图片
性能时间轴上显示减少的事件时间。
这种代码现代化还带来了其他性能改进,如老式设备上的观看加载时间改善、更少的弃播率、更少的 Bug 数量。
总结
通过 YouTube 对性能的投入,观看页面加载得更快了,现在 YouTube 移动网站中的 76% 的 URL 可以在实际场景中通过 Core Web Vitals 的阈值。在桌面端,观看页面的实验室 LCP 从约 4.6 秒减少到 1.6 秒。特别是 YouTube 视频播放器的交互和渲染性能,与以前相比 JavaScript 执行时间减少了高达 75%。
成功:
YouTube 移动网页的 76% URL 现在可以通过 Core Web Vitals,观看时间等业务指标也得到了改进。
过去一年 YouTube 网页性能的改进也提高了业务指标,包括观看时间和日活跃用户。基于这些工作的成功,我们计划在未来继续探索更多优化方法。
在该系列的第二部分“建设一个可访问的 Web”中,你将了解 YouTube 如何使网站对屏幕阅读器用户更具可访问性。
特别感谢 Gilberto Cocchi、Lauren Usui、Benji Bear、Bo Aye、Bogdan Balas、Kenny Tran、Matthew Smith、Phil Harnish、Leena Sahoni、Jeremy Wagner、Philip Walton、Harleen Batra 以及 YouTube 和 Chrome 团队对这项工作的贡献。