由于自己最近一年半的事件都在做视频页面相关的, 而且这次 Netflix 的技术栈也与我们相似, 因此翻译这篇文章, 希望大家一起学习. 页面很多细节值得深入, 但是整个分析下来其实给我们自己在做页面优化提供基本的思路.
Netflix https://netflix.com/ 目前是全球非常非常出色的流媒体服务网站. 自从 2016 年发布之后, Netflix 发现用户不仅会在移动端设注册, 也会在 web 上完成注册相关.
通过优化登出页面使用的 JavaScript 代码, 以及 , 开发者给用户提供了更好的体验, 以及多个方向的改善:
加载以及可交互时间 (Time-to-Interactive) 缩短了 50%;
JS Bundle 的体积减小了 200 KB , 他们选择在客户端更为纯粹的 JS 库, 但是服务端依旧选择 React 来渲染;
通过 Prefetching 一些 CSS 和 JS , 缩短了 30% 的可交互时间在跳转的其他页面的时候.
通过削减 JS 来降低可交互时间
Netflix 工程师是优化用户准备注册和完成登录的页面,
这个页面初始化包含了 300kB 的 JavaScript 代码, 这其中包括基本的 React 文件, 和一些第三方库( https://github.com/lodash/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 + 演讲:
结论
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》 https://www.youtube.com/watch?v=TmhJN6rdm28 .
来源: https://juejin.im/entry/5be843d66fb9a049d5190236