Skip to content

服务器组件

耶和博

2141字约7分钟

2024-08-10

服务器组件

React 服务器组件允许你编写可以在服务器上渲染和可选缓存的 UI。在 Next.js 中,渲染工作进一步按路由段分割,以实现流式传输和部分渲染,有三种不同的服务器渲染策略:

本页将介绍服务器组件的工作原理、何时使用它们以及不同的服务器渲染策略。


服务器渲染的优势

在服务器上进行渲染工作有几个好处,包括:

  • 数据获取: 服务器组件允许你将数据获取移到服务器上,更接近你的数据源。这可以通过减少渲染所需的数据获取时间和客户端需要发出的请求数量来提高性能。
  • 安全性: 服务器组件允许你将敏感数据和逻辑保留在服务器上,如令牌和 API 密钥,而不会有暴露给客户端的风险。
  • 缓存: 通过在服务器上渲染,结果可以被缓存并在后续请求和用户之间重复使用。这可以通过减少每个请求的渲染和数据获取量来提高性能并降低成本。
  • 性能: 服务器组件为你提供了额外的工具来优化基线性能。例如,如果你从一个完全由客户端组件组成的应用开始,将 UI 的非交互部分移到服务器组件可以减少所需的客户端 JavaScript 量。这对于网速较慢或设备性能较低的用户有益,因为浏览器需要下载、解析和执行的客户端 JavaScript 更少。
  • 初始页面加载和首次内容绘制 (FCP): 在服务器上,我们可以生成 HTML 让用户立即查看页面,而无需等待客户端下载、解析和执行渲染页面所需的 JavaScript。
  • 搜索引擎优化和社交网络分享: 渲染的 HTML 可以被搜索引擎机器人用来索引你的页面,社交网络机器人用来生成你页面的社交卡片预览。
  • 流式传输: 服务器组件允许你将渲染工作分割成块,并在准备就绪时将它们流式传输到客户端。这允许用户在整个页面完成渲染之前就能看到页面的部分内容。

在 Next.js 中使用服务器组件

默认情况下,Next.js 使用服务器组件。这允许你自动实现服务器渲染,无需额外配置,并且在需要时可以选择使用客户端组件,参见客户端组件


服务器组件是如何渲染的?

在服务器上,Next.js 使用 React 的 API 来协调渲染。渲染工作被分成块:按个别路由段和 Suspense 边界

在服务器上,Next.js 使用 React 的 API 来协调渲染。渲染工作被分成块:按个别路由段和 Suspense 边界

每个块分两步渲染:

  1. React 将服务器组件渲染成一种称为 React 服务器组件有效负载(RSC Payload) 的特殊数据格式。
  2. Next.js 使用 RSC Payload 和客户端组件 JavaScript 指令在服务器上渲染 HTML

然后,在客户端:

  1. HTML 用于立即显示路由的快速非交互预览 - 这仅适用于初始页面加载。
  2. React 服务器组件有效负载用于协调客户端和服务器组件树,并更新 DOM。
  3. JavaScript 指令用于水合客户端组件并使应用程序具有交互性。

提示

什么是 React 服务器组件有效负载(RSC)?

RSC Payload 是渲染的 React 服务器组件树的紧凑二进制表示。React 在客户端使用它来更新浏览器的 DOM。RSC Payload 包含:

  • 服务器组件的渲染结果
  • 客户端组件应该渲染的位置的占位符以及它们的 JavaScript 文件的引用
  • 从服务器组件传递到客户端组件的任何 props

服务器渲染策略

服务器渲染有三个子集:静态、动态和流式传输。

静态渲染(默认)

使用静态渲染,路由在构建时渲染,或在数据重新验证后在后台渲染。结果被缓存并可以推送到内容分发网络(CDN)。这种优化允许你在用户和服务器请求之间共享渲染工作的结果。

当路由有不针对用户个性化且可以在构建时知道的数据时,静态渲染很有用,例如静态博客文章或产品页面。

动态渲染

使用动态渲染,路由在请求时为每个用户渲染。

当路由有针对用户个性化的数据或只能在请求时知道的信息时,动态渲染很有用,例如 cookies 或 URL 的搜索参数。

提示

带缓存数据的动态路由

在大多数网站中,路由并不是完全静态或完全动态的 - 这是一个范围。例如,你可以有一个电子商务页面,使用缓存的产品数据(以一定间隔重新验证),但也有未缓存的个性化客户数据。

在 Next.js 中,你可以有动态渲染的路由,同时包含缓存和未缓存的数据。这是因为 RSC Payload 和数据是分开缓存的。这允许你选择动态渲染,而不用担心获取所有数据在请求时对性能的影响。

了解更多关于完整路由缓存数据缓存的信息。

切换到动态渲染

在渲染过程中,如果发现动态函数或未缓存的数据请求,Next.js 将切换到动态渲染整个路由。这个表格总结了动态函数和数据缓存如何影响路由是静态还是动态渲染:

动态函数数据路由
已缓存静态渲染
已缓存动态渲染
未缓存动态渲染
未缓存动态渲染

在上表中,要使路由完全静态,所有数据都必须被缓存。然而,你可以有一个动态渲染的路由,同时使用缓存和未缓存的数据获取。

作为开发者,你不需要在静态和动态渲染之间做选择,因为 Next.js 会根据使用的功能和 API 自动为每个路由选择最佳的渲染策略。相反,你选择何时缓存重新验证特定数据,并且你可以选择流式传输你的 UI 的部分。

动态函数

动态函数依赖于只能在请求时知道的信息,例如用户的 cookies、当前请求头或 URL 的搜索参数。在 Next.js 中,这些动态 API 是:

使用这些函数中的任何一个都会使整个路由在请求时选择动态渲染。

流式传输

图表显示了流式传输期间路由段的并行化,展示了单个块的数据获取、渲染和水合过程。

流式传输使你能够从服务器逐步渲染 UI。工作被分割成块,并在准备就绪时流式传输到客户端。这允许用户在整个内容完成渲染之前立即看到页面的部分内容。

图表显示了客户端上部分渲染的页面,正在流式传输的块显示加载 UI。

流式传输默认内置于 Next.js App Router 中。这有助于改善初始页面加载性能,以及依赖于较慢数据获取的 UI,这些数据获取会阻塞整个路由的渲染。例如,产品页面上的评论。

你可以使用 loading.js 和带有 React Suspense 的 UI 组件开始流式传输路由段。有关更多信息,请参阅加载 UI 和流式传输部分。