| 9 min read

原文地址: https://medium.com/dev-channel/a-netflix-web-performance-case-study-c0bcde26a9d9

由于自己最近一年半的事件都在做视频页面相关的,而且这次 Netflix 的技术栈也与我们相似,因此翻译这篇文章,希望大家一起学习。页面很多细节值得深入,但是整个分析下来其实给我们自己在做页面优化提供基本的思路。

Netflix 目前是全球非常非常出色的流媒体服务网站。自从 2016 年发布之后,Netflix 发现用户不仅会在移动端设注册,也会在 Web 上完成注册相关。

通过优化登出页面使用的 JavaScript 代码,以及 prefetching, 开发者给用户提供了更好的体验,以及多个方向的改善:

  • 加载以及可交互时间 (Time-to-Interactive) 缩短了 50%;
  • JS Bundle 的体积减小了 200 KB ,他们选择在客户端更为纯粹的 JS 库,但是服务端依旧选择 React 来渲染;
  • 通过 Prefetching 一些 CSS 和 JS ,缩短了 30% 的可交互时间在跳转的其他页面的时候。

通过削减 JS 来降低可交互时间

Netflix 工程师是优化用户准备注册和完成登录的页面,

这个页面初始化包含了 300kB 的 JavaScript 代码,这其中包括基本的 React 文件,和一些第三方库( lodash ) 以及一些包含 React 状态的上下文数据。

所有 Netflix 的网页都基于 React 的服务器端渲染,然后输出 HTML 内容,然后为用户提供客户端的服务,因此新优化主页的结构必须保持一致性从而来确保开发体验的持续性。

通过使用 Chrome 的 DevTools 和 Lighthouse 来模拟在 3G 请求页面的加载,显示需要7秒才能加载,这对于一个简单的登出页面来说太长了,因此调查了改进的可能性。通过一些性能的排查,发现它们服务端渲染的消耗太高了。

通过关闭浏览器中的 JavaScript 功能,并观察网站的哪些元素一致处在运行中的状态,,开发人员必须要确定对于一个登出的主页 React 是否真的必要。

由于页面上的大多数元素都是基本HTML,因此可以使用纯JavaScript替换点击处理和添加 class ,一个语言切换器使用纯 JS 写比 React 版本明显少了 300 行代码。

完整的移植到 纯JavaScript 的列表如下:

  • 基本互动(主页中间的 Tab)
  • 语言切换器
  • Cookie Bannar(适用于非美国访问者)
  • 用于分析的客户端日志记录
  • 性能测量和记录
  • 广告(为了安全起见,在iFrame中沙箱化)

尽管React的初始占用空间仅为45kB,但删除了React,客户端的几个库和相应的应用程序代码将JavaScript的总量减少了超过200kB,导致 Netflix 登出的交互时间缩短了50%以上。

在删除客户端React,Lodash和其他库之前和之后的有效负载比较。

在实验室环境中,我们使用 Lighthouse 验证用户在上面时间可以与 Netflix 页面进行交互;
来自该领域的指标怎么样?使用Chrome用户体验报告,我们可以看到首次输入延迟  - 从用户首次与您的网站互动的时间到浏览器实际上能够响应该互动的时间 - 对桌面上97%的Netflix用户来说很快。这很棒。

第一次输入延迟(FID)衡量用户在与页面交互时的体验延迟。

Prefetching 后续React页面的资源

为了在浏览其已注销的主页时进一步提高性能,Netflix 利用用户在着陆页上花费的时间来预取用户可能登陆的下一页的资源。

这是通过使用两种技术实现的 - 内置的 浏览器 API 和 XHR 预加载。

prefecthing 是内置浏览器API,在页面头标记中的简单请求链接资源。它向浏览器建议可以预取资源(例如HTML,JS,CSS,图像),虽然它不能保证浏览器实际上会预加载资源,而且它缺乏其他浏览器的的支持。

Prefetching vs XHR

另一方面,XHR 多年来一直是浏览器标准,当 Netfli x团队促使浏览器缓存资源时,其成功率达到95%。虽然XHR预取不能用于预取HTML文档,但 Netflix 使用它来为后续页面预取 JavaScript 和 CSS 包。

注意:Netflix的HTTP响应头配置阻止了使用XHR的HTML缓存(它们在第二页的HTML上没有缓存)。链接预取正在按预期工作,因为即使在某个点上没有缓存,它也可以在HTML上工作。

//创建一个新的XHR请求
const xhrRequest = new XMLHttpRequest();
//打开资源请求“prefetch” 
xhrRequest.open('GET','.. / bundle.js',true);
// 火!
xhrRequest.send();

通过使用内置的 prefetch 和 XHR 预取 HTML,CSS 和 JS,可交互时间减少了30%。此实现还不需要重写JavaScript,也不会对已注销的主页的性能产生负面影响,因此提供了一种有价值的工具,可以在极低风险的情况下提高页面性能。

使用 Prefetch,Netflix 开发人员通过分析页面上交互时间指标的减少以及使用Chrome的开发人员工具直接测量资源的缓存命中率来观察改进。

页面优化摘要

通过在 Netflix 登出主页上使用 Prefech 并优化客户端代码,Netflix能够在注册过程中大大提高其交互时间指标。通过使用浏览器 Prefech 和 XHR 预取来预取未来的页面,Netflix 能够将交互时间缩短30%。这是第二页加载,其中包含单页应用程序注册流程的引导代码。

Netflix 团队进行的代码优化表明,虽然 React 是一个有用的库,但它并不会给每个问题提供解决思路。通过从第一个登录页面上的客户端代码中删除 React 代码进行注册,可交互时间的改进率提高了**50%**以上。减少客户端的交互时间也导致用户以更高的速率点击注册按钮,表明代码优化可以带来更好的用户体验。

虽然 Netflix 没有在主页上使用React,但他们为后续页面预取了它。这使他们能够在单页应用程序注册过程的其余部分中利用客户端React。

有关这些优化的更多详细信息,请参阅Tony Edwards的A +演讲:

https://www.youtube.com/channel/UCGGRRqAjPm6sL3-WGBDnKJA

结论

Netflix通过密切关注JavaScript的消耗的成本,发现了改善交互时间的机会。要了解您自己的的网站是否有机会在此处做得更好,您可以使用 这个工具

Netflix决定做出的权衡是使用React对登陆页面进行服务器渲染,同时也在其上预先获取React /其余注册流程的代码。这样可以优化首次加载性能,同时还可以优化其余注册流的加载时间,因为它是一个单页应用程序,因此需要下载更大的JS包大小。

考虑是否利用vanilla JavaScript是您网站中流量的选项。如果您绝对需要使用库,请尝试仅下载用户所需的代码。预取等技术有助于缩短未来页面导航的页面加载时间。

补充说明

  • 然而,Netflix考虑使用Preact,对于具有低交互性的简单页面流,使用vanilla JavaScript对于它们的堆栈来说是一个更简单的选择。

  • Netflix尝试使用Service Workers进行静态资源缓存。当时,Safari不支持API(现在它支持了),但他们现在再次探索它们。Netflix注册流程需要比成员体验更多的旧版浏览器支持。许多用户都会在较旧的浏览器上注册,但会在其原生移动应用或电视设备上观看Netflix。
    Netflix登陆页面非常动态。这是他们在注册流程中经过最严格的A / B测试页面,机器学习模型用于根据位置,设备类型和许多其他因素自定义消息和图像。在近200个国家的支持下,每种衍生产品都存在不同的本地化,法律和价值信息传递挑战。

有关A / B测试的更多信息,请参阅Ryan Burgess 《Testing Into A Better User Experience》

You Can Speak "Hi" to Me in Those Ways