某不存在的视频网站性能拉跨,Chrome 团队出手相助…

首发于公众号 前端从进阶到入院,欢迎关注。

Hi,大家好我是 ssh,今天和大家分享一篇文章,讲述了 Chrome 团队和 Youtube 共同配合,优化了油管这个世界上并不存在的视频网站的性能。

  • 首屏速度更快了
  • 播放器组件大幅度优化
  • 通过 Core Web Vitals 指标的页面比例更高

从这篇分享 Building a Better Web - Part 1: A faster YouTube on web中,你能学习到世界上顶尖的团队是如何相互配合,优化世界各地用户的性能体验。

Chrome 团队经常谈到"建设更棒的 Web",这啥意思呢?Web 体验应该快速可访问,并在用户最需要的时候具备网络可靠性

吃自己的狗食(Eating Your Own Dog Food)是谷歌文化的一部分,所以 Chrome 团队与 YouTube 合作,在"建设更棒的 Web"的新系列中分享了在这个过程中学到的经验教训。这个系列的第一部分将深入探讨 YouTube 如何建立更迅捷的 Web 体验。

YouTube 移动观看页顺利超过 Core Web Vitals设立的阈值。

建设更快的 Web

对于 YouTube 来说,性能和网页上视频和其他内容(如推荐和评论)的加载速度有关。性能也由 YouTube 响应用户交互(如搜索、播放器控制、点赞和分享)的速度决定。

巴西、印度和印度尼西亚等发展中市场对 YouTube 移动网页很重要。由于这些地区的许多用户设备和网速都比较拉跨,确保快速流畅的体验就很关键了。

为了向所有用户提供良好的体验,YouTube 着手通过懒加载和代码现代化来改进Core Web Vitals等性能指标。

改进 Core Web Vitals

为了判断需要改进哪些领域,YouTube 团队使用Chrome 用户体验报告(CrUX)来查看移动端实际的用户在视频观看页面和搜索结果页面的体验,得知了他们的 Core Web Vitals 有很大的改进空间,在某些情况下,最大内容渲染时间(LCP)指标达到 4-6 秒。这远高于他们 2.5 秒的目标。

为了确定改进的细节,他们用Lighthouse来审查 YouTube 观看页面,果然得到了一个较低的 Lighthouse(实验室)分数,首次内容渲染时间(FCP)为 3.5 秒,最大内容渲染时间(LCP) 为 8.5 秒。

Chrome 将 FCP 的目标设置为 1.8 秒,将 LCP 的目标设置为 2.5 秒作为黄金标准。FCP 和 LCP 分别为 3.5 秒和 8.5 秒,明显偏黄和偏红。

为了优化 FCP 和 LCP,YouTube 团队进行了几项实验,得到两个重大的发现。

  1. 第一个发现是,把视频播放器的 HTML 代码移动到视频播放相关的 JS 脚本之上,可以提高性能。实验室测试(Labs test)表明,这可以将 FCP 和 LCP 从 4.4 秒改善到 1.1 秒。

  2. 第二个发现是 LCP 只考虑<video>元素的海报图,而不考虑视频流本身的帧。YouTube 一直在优化视频开始播放的最快时间,为了改进 LCP,团队开始优化他们可以交付海报图的速度。他们尝试了几种海报图的变体,并选择了在用户测试中得分最高的一种。作为这项工作的结果,FCP 和 LCP 都取得了显著改进,实际场景中的 LCP 从 4.6 秒提高到 2.0 秒。

在实验测试中,我们观察到这个更改落地后,FCP 和 LCP 从 4.4 秒提升到 1.1 秒。

  • 实验 A:用实际的视频暂停截图作为海报图,用户表现不佳,导致用户活跃下降。

  • 实验 B:使用实心黑色缩略图作为海报,结果很好,用户发现从实心黑色过渡到视频的第一帧,体验是很平稳的。

2021 年 7 月,黑色缩略图的方案部署成功,如上面的 RUM 分析所示,FCP 和 LCP 有显著改进。

在将这些优化引入所有平台的同时,YouTube 还利用了新的fetchpriority属性,我们将它与<link rel=preload>一起使用,以优先发现和加载海报图:

html 复制代码
<link as="image" rel="preload" href="poster.jpg" fetchpriority="high" />

虽然这些优化确实改进了 LCP,但团队觉得 LCP 指标的当前定义并没有完全捕获用户视角中的"主要内容"何时加载------这是 LCP 的目标。

为了解决这些问题,YouTube 团队的成员与 Chrome 团队的成员合作,探索改进 LCP 指标的方式,以解决他们的用例。在考虑了几个选项的可行性和影响后,两支团队得出的建议是将视频元素的第一帧的绘制时间视为 LCP 候选项。

一旦这个变化在 Chrome 中落地,YouTube 团队就能开心的继续优化 LCP 了。这个指标更加接近用户真实的体验。

模块化与懒加载

YouTube 页面包含许多直接加载的模块。为了优化 50 多个组件的渲染方式,团队建立了一个组件到 JS 模块的 map,这个 map 将告诉客户端加载哪些模块。通过将组件标记为懒加载,JS 模块会晚一些加载,从而减少页面的初始加载时间和未使用 Javascript 的数量。

然而,在实现懒加载后,团队注意到懒加载的组件及其依赖项会在次优级时间批量加载。

为了解决这个问题,团队确定了视图中所需的最小组件集,并将它们打包在一个 Web 请求中。结果是页面速度得到改善,JavaScript 解析时间减少,最终得到了更好的初始渲染时间。

跨组件状态管理

YouTube 由于其播放器控件而遇到性能问题,特别是在较旧的设备上。代码分析显示,播放器(允许用户控制播放速度、进度等功能)随着时间的推移变得过度组件化了。

YouTube 视频播放器允许用户控制播放速度、跟踪进度、跳过部分等。当用户点击特定控件时,状态变化必须传达给其他控件,例如,用户点击进度条必须与播放头部、字幕等控件共享。

实验性能测试运行中,每次触摸移动进度条事件会额外触发两次样式重绘,花费 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 团队对这项工作的贡献。

首发于公众号 前端从进阶到入院,作者 ssh,工作 6 年+,阿里云、字节跳动 Web infra 一线拼杀出来的资深前端工程师 + 面试官,非常熟悉大厂的面试套路,Vue、React 以及前端工程化领域深入浅出的文章帮助无数人进入了大厂,关注后回复「指南」,获取高级前端、算法学习路线,是我自己一路走来的实践。

相关推荐
john_hjy18 分钟前
【无标题】
javascript
奔跑吧邓邓子31 分钟前
npm包管理深度探索:从基础到进阶全面教程!
前端·npm·node.js
软件开发技术深度爱好者40 分钟前
用HTML5+CSS+JavaScript庆祝国庆
javascript·css·html5
前端李易安1 小时前
ajax的原理,使用场景以及如何实现
前端·ajax·okhttp
汪子熙1 小时前
Angular 服务器端应用 ng-state tag 的作用介绍
前端·javascript·angular.js
Envyᥫᩣ2 小时前
《ASP.NET Web Forms 实现视频点赞功能的完整示例》
前端·asp.net·音视频·视频点赞
Мартин.5 小时前
[Meachines] [Easy] Sea WonderCMS-XSS-RCE+System Monitor 命令注入
前端·xss
昨天;明天。今天。7 小时前
案例-表白墙简单实现
前端·javascript·css
数云界7 小时前
如何在 DAX 中计算多个周期的移动平均线
java·服务器·前端
风清扬_jd7 小时前
Chromium 如何定义一个chrome.settingsPrivate接口给前端调用c++
前端·c++·chrome