原文作者:Addy Osmani
译者:UC 国际研发 Jothy
太长不看版:没有实现 Web 性能的万能武器。 简单的静态页面由于使用最小的 JavaScript 进行服务端渲染而快速展示。 在谨慎使用情况下,库可以为复杂页面提供巨大的价值。
本文主要给大家分享Netflix.com 桌面版是如何提升交互时间的,欢迎阅读。
Netflix 是最受欢迎的视频流服务之一。 自 2016 年在全球推出以来,该公司发现许多新用户不仅在移动端注册,而且还用了不太理想的网络连接。
通过改进 Netflix.com 注册过程的 JavaScript 和使用预获取(prefetch)技术,开发团队为移动和桌面用户提供了更好的用户体验以及多项改进。
加载和交互时间减少了 50%(对于 Netflix.com 上已注销的桌面主页)
由于从 React 和其他客户端库切换到原生 JavaScript,JavaScript 包大小减少了 200kB。 React 仍在服务器端使用。
预获取 HTML,CSS 和 JavaScript(React)将未来导航可交互时间缩短了 30%。
通过少传输 JS 来缩短交互时间
Netflix 开发者进行了性能优化的区域是注销后的主页,用户可以在该页上注册或登录该站点。
Netflix.com主页,适用于新用户和未登录的用户
该页面最初包含 300kB 的 JavaScript,其中一些是 React 和其他客户端代码(如 Lodash 等工具库),还有一些是保存 React 状态所需的上下文数据。
所有 Netflix 的网页都由 React 实现服务端渲染,生成 HTML,然后服务客户端应用,因此保持最新优化的主页结构就像保持一致的开发体验一样,都非常重要。
主页选项卡是最早使用 React 编写的组件示例
使用 Chrome 的 DevTools 和 Lighthouse 模拟在 3G 网络上加载的已退出(未登录)的主页,页面显示需要 7 秒才能加载出来,这对于一个简单的登录页面来说太长了,因此这部分的提升潜力得到了关注。 通过一些性能审计,Netflix 发现他们的客户端 JS 成本很高。
通过关闭浏览器中的 JavaScript 并观察网站的哪些元素仍然可以运行,开发团队可以确定已退出(未登录)主页是否真的需要 React 才能运行。
由于页面上的大多数元素都是基本 HTML,因此可以使用纯 JavaScript 替换 JavaScript 点击处理和类添加等其余元素。最初使用 React 构建的页面语言切换器被换成了不到 300 行的原生 JavaScript 代码重构。
移植到原生 JavaScript 的完整组件列表如下:
- 基本互动(主页中间的标签)
- 语言切换器
- Cookie 横幅(适用于非美国访问者)
- 用于分析的客户端日志
- 性能测量和日志
- 广告归因像素引导代码(出于安全原因而在 iFrame 中沙箱化)
尽管 React 的初始占用空间仅为 45kB,但删除了 React、客户端的几个库和相应的应用代码后,JavaScript 的总大小减少了超过 200kB,最终使 Netflix 已退出(未登录)主页的交互时间缩短了 50% 以上。
在实验室环境中,我们可以验证用户已能使用 Lighthouse(trace) 快速与 Netflix 主页进行交互。 桌面 TTI < 3.5s。
来自该领域的指标又是怎么样? 使用 Chrome 用户体验报告,我们可以看到首次输入延迟 - 从用户首次与网站互动到浏览器实际响应该互动的时间 - 对 97% 的桌面版 Netflix 用户来说很快。 这太棒了。
预取后续页面的 React
为了进一步提升用户浏览已退出(未登录)主页时的性能,Netflix 利用了用户在登录页上花费的时间来预获取用户可能进入的下一页的资源。
这是通过使用两种技术实现的 - 内置的 浏览器 API 和 XHR 预获取。
内置浏览器 API 包含页面头标记中的简单链接标记。 它向浏览器建议可以预取资源(例如 HTML,JS,CSS,图片),但它不能保证浏览器能实际获取到该资源,并且它缺乏其他浏览器的完全支持。
预取技术的比较
另一方面,XHR 预获取多年来一直是浏览器标准,当 Netflix 团队促使浏览器缓存资源时,其成功率达到 95%。 由于 XHR 预获取不能用于预获取 HTML 文档,因此 Netflix 使用它来预获取后续页面的 JavaScript 和 CSS。
注意:Netflix 的 HTTP 响应头配置阻止了使用 XHR 的 HTML 缓存(它们在第二页的 HTML 上没有缓存)。 Link Prefetch 正按预期工作,因为即使在某个点上没有缓存,它也可以在 HTML 上工作。
通过使用内置的浏览器 API 和 XHR 预取 HTML,CSS 和 JS,交互时间减少了 30%。 此实现不需要重写 JavaScript,也不会对已退出(未登录)主页的性能产生负面影响,因此它提供了一种有价值的工具,可以在极低风险的情况下提升页面性能。
实现预获取后,Netflix 开发人员通过分析页面上交互时间指标的减少,以及使用 Chrome 的开发者工具直接测量资源的缓存命中率来观察到了提升。
Netflix 已退出(未登录)主页 - 优化摘要
通过在 Netflix 已退出(未登录)主页上预获取资源以及优化客户端代码,Netflix 极大的提升了其注册过程中的交互时间指标。通过使用内置浏览器 API 和 XHR 预获取技术来预获取未来页面,Netflix 将交互时间缩短了 30%。这是对于二次加载而言,其中包含单页面应用注册流程的引导代码。
Netflix 团队进行的代码优化表明,虽然 React 是一个有用的库,但它可能无法为每个问题提供充分的解决方案。通过从第一个登录页面上的客户端代码中删除用于注册的 React 代码,交互时间的改进率提高了 50% 以上。减少客户端的交互时间也能使用户以更高的速率点击注册按钮,这表明代码优化可以带来更好的用户体验。
虽然 Netflix 没有在主页上使用 React,但他们为后续页面预获取了它。这使他们能够在单页面应用注册过程的其余部分中利用客户端 React。
有关这些优化的更多详细信息,请参阅 Tony Edwards 的 A+ 演讲:
https://www.youtube.com/watch?time_continue=1&v=V8oTJ8OZ5S0
结论
Netflix 通过密切关注 JavaScript 的成本,发现了改善交互时间的机会。 要了解你的网站是否有改进机会,请问问你的性能工具。
Netflix 做出的权衡是使用 React 对登录页面进行服务端渲染,同时也在其上预获取 React/其余注册流程的代码。 这样不仅可以优化首次加载性能,还可以优化其余注册流的加载时间,因为它是一个单页面应用,因此需要下载更大的 JS 包。
考虑是否利用原生 JavaScript 是网站中流量的选项。 如果你必须需要使用库,那么请尝试仅下载用户所需的代码。 预获取等技术有助于缩短未来页面导航的页面加载时间。
额外的提醒
Netflix 考虑使用 Preact,但对于交互性低的简单页面流而言,使用原生 JavaScript 对于它们的堆栈来说是一个更简单的选择。
Netflix 尝试使用 Service Workers 进行静态资源缓存。 当时,Safari 不支持该API(现在支持了),但他们正在再次探索。 Netflix 注册流程相比会员体验,需要对更多旧版浏览器支持。许多用户都会在较旧的浏览器上注册,但会在其原生移动应用或电视设备上观看 Netflix。
Netflix 登录页面非常动态化。 这是他们注册流程中最严格的 A/B 测试页面,它使用机器学习模型,根据位置,设备类型和许多其他因素来自定义消息和图像。 在近 200 个国家的支持下,每种衍生产品都存在不同的本地化,法律和价值信息传递挑战。 有关 A/B 测试的更多信息,请参阅 Ryan Burgess 的「 Testing Into A Better User Experience」。
感谢 Netflix UI 工程师,Tony Edwards,Ryan Burgess,Brian Holt,Jem Young,Kristofer Baxter(Google),Nicole Sullivan(Chrome)和 Houssein Djirdeh(Chrome)的评论和贡献。