Airbnb 引入 HTTP Streaming,网页性能升级

作者| Rafal Gancarz

译者| 明知山

策划| 丁晓昀

Airbnb 通过引入 HTTP Streaming 来提升网站的页面加载性能。他们将测试的每个页面(包括主页)的首次内容绘制(First Contentful Paint,FCP)时间降低了大约 100 毫秒。他们还最小化了后端慢查询对加载时间的影响。

Airbnb 一直在尝试进行可能的改进,以便尽可能快地向网站用户呈现内容。他们发现,只在完全渲染后才发送页面主体并不能提供最佳的用户体验,特别是当页面主体内容依赖后端查询时。此外,网页通常还需要许多额外的资源,如 CSS 文件和外部 JavaScript 文件,浏览器需要下载这些文件,以便正确地向用户显示内容。这些依赖关系经常导致资源请求发生级联,这可以在网络序列视图中看出来,比如 Chrome 的 Waterfall。

图片来源:https://medium.com/airbnb-engineering/improving-performance-with-http-streaming-ba9e72c66408

一种允许浏览器更早下载外部资源的常见做法是将所有引用它们的标记放在 HTML 页面头部的标签中。浏览器在读取标签时会下载外部资源。通常,这只会在整个 HTML 页面被传输后才会发生,如果页面内容依赖了缓慢的后端查询,则可能需要一些时间。

尽早冲刷(Early Flush)是一种利用 HTTP Streaming 技术让浏览器可以更早地加载外部资源的技术。它需要将 HTML 页面分成两个部分,并使用分块传输编码分别发送它们。在接收并解析了只包含 HTML 页面开头部分的初始块后,浏览器就可以开始下载外部资源。

尽管尽早冲刷并不是什么新技术,但也并没有被广泛使用,因为它需要渲染和发送不完整的 HTML 页面(有些标签没有关闭)。Airbnb 使用基于 Express 的 NodeJS 服务器来渲染 React 开发的网页,并将之前用于渲染整个 HTML 页面的单个 React 组件重新设计拆分为三个单独的组件。

尽早冲刷技术有助于优化 CSS 和 JavaScript 资源的 Waterfall 指标,但并不会降低渲染页面主体的延迟。使用现代 Web 应用程序框架可以在客户端或服务器端渲染内容(服务器端渲染)并分别获取数据,但这需要额外的网络请求。

Airbnb 的 Streaming 处理方法经过了改进,他们引入了第三个块(他们称之为延迟数据块),其中包含了页面所需的数据。他们使用 MutationObserver 来检测延迟的数据何时被加载,并将数据注入到应用程序网络数据存储中,从而避免了额外的网络请求。

服务器端渲染(SSR)和客户端数据获取并行执行

图片来源:https://medium.com/airbnb-engineering/improving-performance-with-http-streaming-ba9e72c66408

Airbnb 必须解决一些问题才能在他们的技术栈中启用 HTTP Streaming。他们关闭了 NGINX 中的响应缓冲和 haproxy 负载均衡器中的 Nagle 算法,允许块响应数据可以不经修改地到达浏览器。

Airbnb 软件工程师 Victor Lin 总结了他们在这方面的经验,以及一个不断增长的支持 HTTP Streaming 的生态系统:

虽然这个过程充满了挑战,但我们发现,调整现有的 React 应用程序来支持 Streaming 是非常可行和健壮的,尽管最初并不是为了它而设计的。我们也很高兴看到更广泛的前端生态系统朝着优先化 Streaming 的方向发展——从 GraphQL 的 @defer 和 @stream 到 Next.js 的 Streaming SSR。

原文链接

https://www.infoq.com/news/2023/06/airbnb-web-http-streaming/