Netflix 网页性能优化实践

作者|Addy Osmani 译者|谢丽 通过改进 Netflix.com 注册过程中所使用的 JavaScript 及预加载技术,Netflix 开发团队为移动用户和桌面用户提供了更好的用户体验。 关于 Web 性能,没有银弹,简单的静态页面包含极少的 JavaScript,可以从服务器渲染受益。库的谨慎使用可以为复杂的页面带来巨大的价值。 Netflix 是最受欢迎的视频流服务之一。自 2016 年在全球推出以来,该公司发现,许多新用户不仅在移动设备上进行了注册,还使用了不太理想的连接。 通过改进 Netflix.com 注册过程中所使用的 JavaScript 及预加载技术,开发团队能够为移动用户和桌面用户提供更好的用户体验,主要改进如下。

  • 加载和交互时间减少了 50%(Netflix.com 桌面登录主页);
  • 在从 React 和其他客户端库切换到普通的 JavaScript 之后,JavaScript 包大小减少了 200KB。服务器端仍然使用 React。
  • HTML、CSS、JavaScript(React)预加载使后续页面的浏览交互时间减少了 30%。

减少 JavaScript 传输,缩短交互时间

Netflix 针对其登录主页的性能进行了优化,用户在这个页面上注册或登录到网站。 图片 这个页面最初包含 300KB 的 JavaScript,其中一些是 React 和其他客户端代码(比如像 Lodash 这样的实用程序库),还有一些是补充 React 状态所需的上下文数据。 Netflix 的所有网页都由服务器端渲染的 React 提供,提供生成的 HTML,然后提供客户端应用程序,因此,新优化的主页要保持结构类似,为开发人员提供一致的体验,这很重要。 图片 使用 Chrome 的开发工具和 Lighthouse 模拟在 3G 连接上加载登录主页,结果显示,登录主页需要 7 秒的加载时间,对于一个简单的登录页面来说太长了,因此需要研究改进的可能。通过一些性能审计,Netflix 发现他们客户端的 JS 开销很高。 图片 Chrome 开发工具中 Netflix.com 优化前的网络节流 通过在浏览器中关闭 JavaScript 并观察站点的哪些元素仍起作用,开发团队可以确定登录主页是否真得需要 React。 由于页面上的大多数元素都是基本的 HTML,剩下的元素(如 JavaScript 单击处理和类添加)可以用普通的 JavaScript 替换,并且页面的语言切换器(最初使用 React 构建)用普通的 JavaScript 重新构建只用了不到 300 行代码。 移植到普通 JavaScript 的组件列表:

  • 基础交互(主页选项卡)
  • 语言切换器
  • “Cookie 横幅(Cookie banner)”(针对非美国用户)
  • 客户端日志分析
  • 性能度量和记录
  • 广告归属检测引导代码(出于安全考虑,放在沙箱式 iFrame 中) 图片 尽管 React 最初占用的空间仅为 45KB,但将 React、几个库和相应的应用程序代码从客户端移除后,JavaScript 的总量减少了 200KB 以上,这使得 Netflix 在登录主页的交互时间减少了 50% 以上。 图片 删除客户端 React、Lodash 和其他库前后的负载比较。 在 实验室 环境中,我们可以使用 Lighthouse(trace)验证,用户现在可以与 Netflix 主页快速交互。桌面 TTI 小于 3.5 秒。 图片 交互时间优化后的 Lighthouse 报告 实际指标呢?使用 Chrome 用户体验报告,我们可以看到,首次输入延迟——从用户第一次与你的网站交互到浏览器真正响应那次交互的时间——对于 97% 的 Netflix 桌面用户来说是 非常快 的。这很棒。 图片 首先输入延迟(FID)度量用户在与页面交互时的延迟体验。

后续页面的 React 预加载

为了进一步提高浏览登录主页的性能,Netflix 利用用户在登录页面上花费的时间对于用户可能会登录的下一个页面进行预加载。 这是通过浏览器内置的 API 和 XHR 预加载这两项技术实现的。 浏览器内置 API 由页面头部标签内的一个简单链接标签组成。它建议预加载浏览器资源(例如 HTML、JS、CSS、图像),尽管它不能保证浏览器会预加载资源,而且它也没有得到 其他浏览器的完全支持。 图片 预加载技术比较 另一方面,XHR 预加载已经成为浏览器标准多年,当 Netflix 团队提示浏览器缓存资源时,其成功率达到 95%。虽然 XHR 预加载不能用于预加载 HTML 文档,但 Netflix 使用 XHR 预加载后续页面的 JavaScript 和 CSS 包。 注意:Netflix 的 HTTP 响应头配置为使用 XHR 防止缓存 HTML(它们确实不缓存第二个页面的 HTML)。不过,“链接预加载(Link Prefetch)”会按预期工作,因为它对 HTML 有效,即使设置了不缓存。

// 新建一个 XHR 请求
const xhrRequest = new XMLHttpRequest();
// 针对预加载的资源打开请求
xhrRequest.open('GET', '../bundle.js', true);
// 发送!
xhrRequest.send();

通过使用浏览器内置的 API 和 XHR 预加载 HTML、CSS 和 JS,交互时间减少了 30%。这个实现也不需要重写 JavaScript,不会对登录主页的性能造成负面影响,因此,提供了一个很有价值的工具,以非常低的风险提高页面性能。 图片 在实现预加载之后,Netflix 开发人员通过分析页面上交互时间的减少以及使用 Chrome 开发工具直接度量资源缓存命中,观察到了性能的提升。

Netflix 登录主页优化概述

通过预取资源和优化 Netflix 登录主页上的客户端代码,Netflix 能够在注册过程中大大改善其交互时间指标。通过使用浏览器内置的 API 和 XHR 预加载未来页面,Netflix 能够将交互时间减少了 30%。这是对于第二页加载来说的,其中包含单页应用注册过程的引导代码。 Netflix 团队进行的代码优化表明,React 是一个有用的库,但它可能无法为每个问题提供足够的解决方案。通过从第一个用于注册的登录页面的客户端代码中删除 React,交互时间减少了 50% 以上。缩短客户端上的交互时间还会导致用户以更快地速度单击注册按钮,这表明代码优化总体上可以带来更好的用户体验。 虽然 Netflix 没有在主页中使用 React ,但他们会为后续的页面预取。这使得他们整个页面应用程序流程中的其他部分可以利用客户端 React。

小结

通过密切关注 JavaScript 的开销,Netflix 发现了改善交互时间的机会。要了解你的站点是否有机会在这点上做得更好,可以借助性能工具 :https://developers.google.com/web/fundamentals/performance/speed-tools/ Netflix 的折中方案是,使用 React 在服务器端渲染登录页面,但同时也为注册过程的其他部分预取 React 代码。这不仅优化了首次加载性能,还优化了注册过程其余部分的加载时间,因为它是单页应用,所以有更大的 JS 包需要下载。 考虑一下,使用普通的 JavaScript 是否适合站点的流程。如果你确实需要使用库,那么尝试下只下传用户需要的代码。预加载技术可以帮助提高未来浏览页面的加载时间。 补充说明 Netflix 考虑过 Preact,但是,对于一个交互性比较低的简单页面流,使用普通的 JavaScript 是一个更简单的选择。 Netflix 尝试使用 Service Workers 进行静态资源缓存。当时,Safari 不支持这个 API(现在支持了),但他们现在又在探索这个 API。Netflix 的注册过程需要比客户体验更多的遗留浏览器支持。许多用户会在旧的浏览器上注册,但会在他们本地的移动应用程序或电视设备上观看 Netflix。 Netflix 的登录页面极为动态。这是他们的注册过程中进行 A/B 测试最多的页面,机器学习模型用于根据位置、设备类型和许多其他因素定制消息和图像。支持近 200 个国家,每个派生页面都面对着不同的本地化、法律和价值信息挑战。有关 A/B 测试的更多信息,请参阅 Ryan Burgess 的“测试,只为更好的用户体验”。 英文原文:https://medium.com/dev-channel/a-netflix-web-performance-case-study-c0bcde26a9d9 活动推荐 推荐大家关注由 InfoQ 中国主办的 ArchSummit 全球架构师峰会,大会即将于 12 月 7-8 日在北京国际会议中心举办,来自 Google、Netflix、LinkedIn、腾讯、阿里、百度、京东等百位知名企业的架构师都将前来分享各自的架构实践,并特别设置了前端技术专题,分享他们的最新黑科技和研发经验。 9 折优惠购票火热进行中,点击“阅读原文”了解更多详情!票务 MM 灰灰联系方式:17326843116 (微信同号 等你来撩)