最近,我们将主页的性能提高了 10 倍以上。 让我们一起探讨一下我们是如何取得这一成果以及涉及哪些技术的。
首先,我们来看看为什么网站性能如此重要(链接到本文末尾的案例研究):
在本文中,我们将简要介绍以下有助于我们提高页面性能的主要方面:
对于某些情况,我们的主页是使用 React ()、()、() 和 API (Ruby on Rails) 构建的。 移动设备上的界面如下所示:
和
没有数据,绩效衡量就是一句空话。 ——W.
实验室测试工具(实验室)
实验室测试工具允许在具有预定义设备和网络设置的受控环境中收集数据。 使用这些工具,可以更轻松地调试任何性能问题并进行良好的可重复测试。
是一个用于管理本地计算机上的页面的好工具。 它还提供了一些关于如何提高性能、可访问性、搜索引擎优化等的有用提示。 以下是一些模拟快速 3G 和 4 倍 CPU 减速的性能审核报告:
使用 First Paint (FCP) 将性能提高 10 倍之前和之后
然而,仅使用实验室测试工具的缺点是它们可能不一定能发现现实世界的瓶颈,这可能取决于最终用户的设备、网络、位置和许多其他因素。 这就是为什么使用现场测试工具也很重要。
现场测试工具(Field)
实时测试工具使我们能够模拟和测量真实的用户页面负载。 有许多服务可以帮助从真实设备获取真实性能数据:
报告
呈现内容的方法有很多种,每种方法都有其优点和缺点:
客户端渲染
之前,我们将主页与 Ember.js 框架一起实现为具有客户端渲染的 SPA。 我们遇到的一个问题是 Ember.js 应用程序包太大。 这意味着当浏览器下载、解析、编译和执行文件时,用户只能看到一个空白屏幕。
白屏
我们决定使用 React 重建应用程序的某些部分。
预渲染和服务器端渲染
例如,使用 React DOM 构建的客户端渲染应用程序的问题仍然与使用 Ember.js 相同。 昂贵并且需要一些时间才能在浏览器中看到内容的第一次绘制(First Paint)。
一旦我们决定使用 React,我们立即尝试其他潜在的渲染选项,以允许浏览器更快地渲染内容。
使用 React 的通用渲染选项
这就是为什么我们决定尝试一些混合方法,试图充分利用每个渲染选项。
运行时预渲染
是一个允许使用 的 Node.js 库。 我们希望在运行时尝试预渲染。 这实现了一种有趣的混合方法:在服务器端渲染并通过激活在客户端渲染。 以下是 提供的一些关于如何使用无头浏览器进行服务器端渲染的有用提示。
用于在运行时预渲染 React 应用程序
使用这种方法有以下优点:
然而,我们在使用这种方法时遇到了一些挑战:
使用服务器端渲染的架构
AWS 和 GCP 功能的响应时间
随着我们变得更加熟悉,我们迭代了最初的方法(如下所示)。 我们还尝试通过无头浏览器渲染 PDF 进行一些有趣的尝试。 它还可以用于自动端到端测试,甚至无需编写任何代码。 此外,现在它还支持 .
混合渲染方法
在运行时使用具有挑战性。 这就是为什么我们决定在构建时使用它,并使用一个在运行时从服务器端返回实际用户生成的内容的工具。 与 相比,它更稳定,吞吐量更高。
我们决定尝试一下编程语言。 看起来像 Ruby,但运行在 BEAM (VM) 之上,旨在构建容错且稳定的系统。
使用 Actor 并发模型。 每个“Actor”( ) 占用的内存很少,大约 1-2KB。 这允许数千个独立进程同时运行。 是一个支持高吞吐量并在独立进程中处理每个 HTTP 请求的 Web 框架。
我们将这些方法结合起来,充分利用各自的优势,来满足我们的需求:
用于预渲染,而用于服务端渲染
我们可以继续构建一个简单的浏览器 React 应用程序,该应用程序可以快速加载初始页面,而无需等待最终用户的设备。
这使得内容搜索引擎优化变得友好,允许根据需要处理尽可能多的不同页面,并且更容易扩展。
通过这种方式,我们可以构建高度交互的应用程序并访问浏览器功能。
使用 React 进行预渲染、使用服务器端渲染以及使用 React 进行 React
网络
内容分发网络 (CDN)
使用 CDN 可以缓存内容并加快其在全球的分发速度。 我们使用它,它服务于所有互联网请求的 10% 以上,并被各种公司使用,例如 、 、 等。
允许我们使用称为 VCL 的配置语言编写自定义缓存和路由逻辑。 下图显示了基本请求流程的工作原理,根据路由、请求标头等自定义每个步骤:
VCL请求流程
提高性能的另一个选择是使用 (WASM) 和 . 可以将其想象为使用无服务器,但处于使用 C、Rust、Go 等编程语言的边缘。 上面有一个类似的项目支持 WASM。
缓存
缓存尽可能多的请求对于性能非常重要。 CDN 级别的缓存可以为新用户提供更快的响应。 通过发送 Cache- 进行缓存可以加快浏览器中重复请求的响应时间。
大多数构建工具(例如)允许向文件名添加哈希值。 这些文件可以安全地缓存,因为更改文件将创建新的输出文件名。