[译] Netflix 的 Web 性能案例研究

2018-11-18 16:31:08 +08:00
 Harldwell

提纲:Web 性能优化没有银弹。简单的静态网页得益于使用极少 JavaScript 代码的服务端渲染。库的谨慎使用可以为复杂的页面带来巨大的价值。

Netflix 是最受欢迎的视频流服务之一。自 2016 年在全球推出以来,公司发现许多新用户不仅通过移动设备完成注册,而且还使用了不太理想的网络连接。

通过改进用于 Netflix.com 注册过程 JavaScript 代码和使用预加载技术,开发人员团队可以为移动和桌面用户提供更好的用户体验,并提供多项改进。

通过嵌入更少的代码来减少可交互时间

Netflix 开发者优化性能的地方是未登录主页,用户在此页面注册并登录站点。

新用户和已登出用户的 Netflix.com 主页

此页面初始包含 300KB 的 JavaScript 代码,其中一些是 React 和其他客户端代码(例如像 Lodash 的工具库),而且还有一些是必要的上下文数据用来给 React 的状态注水( hydrate )。

所有 Netflix 的网页都由服务端 React 渲染,这些页面为生成的 HTML 和客户端应用提供服务,因此维持新优化的主页结构不变和保持开发人员体验的一致性同样重要。

Homepage 选项卡是最初使用 React 编写的组件的示例

使用 Chrome 的 DevTools 和 Lighthouse 来模拟 3G 网络下加载未登录主页,结果显示未登录主页需要 7 秒时间来加载,这段时间对于一个简单的入口页面来说实在是太久了,所以我们开始调查改进的可能性。通过一些性能审查,Netflix 发现他们的客户端 JS 有过高的开销。

通过 Chrome DevTools 的网络限速功能,查看未优化的 Netflix.com 的表现。

通过关闭浏览器中的 JavaScript 来观察站点中仍在起作用的元素,开发者团队可以决定 React 在未登录主页是否真正必要。

由于页面中的多数元素是基本的 HTML,剩下的元素比如 JavaScript 点击处理和添加类可以用原生 JavaScript 来替换,而页面原来使用 React 实现的语言切换器则使用不到 300 行的原生 JavaScript 代码重构。

移植到原生 JavaScript 的组件完全列表:

虽然 React 的初始代码仅仅 45 KB,在客户端移除 React、一些库和相应的 App 代码 减少的 JavaScript 代码总量超多 200 KB ,由此在 Netflix 的未登录主页降低了超过 50% 的可交互时间。

移除客户端 React、Lodash 和其他一些库前后的负载比较。

在实验环境下,我们可以使用 Lighthouse ( trace )快速测验用户是否能与 Netflix 主页交互。结果桌面端的 TTI 少于 3.5s 。

可交互时间优化后的 Lighthouse 报告。

那么这个领域的度量标准呢?使用 Chrome 用户体验报告我们可以看到首次输入延迟 —— 从用户首次与你的站点交互时间到浏览器真正响应那次交互的时间 —— 对于 97% 的 Netflix 桌面用户来说很快。结果非常棒。

首先输入延迟( FID )度量用户在与页面交互时的延迟体验。

为后续页面预加载 React

为了进一步提高浏览登录主页的性能,Netflix 利用用户在入口页面上花费的时间针对可能会登录的下一个页面进行资源 预加载 。

通过两项技术完成 —— 内置的 <link rel=prefetch> 浏览器 API 和 XHR 预加载。

内置的浏览器 API 包含页面头部标签内的简单链接标签。它会建议浏览器资源(例如 HTML、JS、CSS、图片)可以被预加载,虽然它并不保证浏览器真的  预加载资源,并且它缺少其他浏览器的全面支持。

预加载技术对比

另一方面,XHR 预加载已经成为浏览器标准很多年了,当 Netflix 团队提示浏览器缓存资源时,其成功率达到 95%。但是 XHR 预加载不能预加载 HTML 文档,Netflix 用它来为后续页面预加载 JavaScript 和 CSS 打包文件。

注意:Netflix 配置的 HTTP 响应头禁止使用 XHR 缓存 HTML (它们确实不缓存( no-cache )第二个页面的 HTML )。链接预加载会按预期工作,因为它对 HTML 有效,即使设置了不缓存( no-cache )。

// 创建新的 XHR 请求
const xhrRequest = new XMLHttpRequest();

// open the request for the resource to "prefetch"
// 打开请求来“预加载”资源
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。

更多关于这些优化的细节,请观看 Tony Edwards 的出色演讲:

总结

通过密切关注 JavaScript 的开销,Netflix 发现了改善可交互时间的机会。若想发现你的站点是否有机会在这点上做得更好,可以借助你的性能工具。

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

考虑一下是否使用原生 JavaScript 是否适合你的站点的流程。如果你确实需要使用库,那么尝试只嵌入你的用户需要的代码。预加载技术可以帮助优化未来浏览页面的加载时间。

本次给大家推荐一个免费的学习群,里面概括移动应用网站开发,css,html,webpack,vue node angular 以及面试资源等。 对 web 开发技术感兴趣的同学,欢迎加入 Q 群:943129070,不管你是小白还是大牛我都欢迎,还有大牛整理的一套高效率学习路线和教程与您免费分享,同时每天更新视频资料。 最后,祝大家早日学有所成,拿到满意 offer,快速升职加薪,走上人生巅峰。

1571 次点击
所在节点    推广
0 条回复

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/508972

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX