Skip to main content

服务器组件

React 服务器组件允许您编写可以在服务器上渲染和可缓存的 UI。在 Next.js 中,渲染工作进一步按路由段进行拆分,以支持流式渲染和部分渲染,并且有三种不同的服务器渲染策略:

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

服务器渲染的好处

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

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

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

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

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

在服务器端,Next.js 使用 React 的 API 来协调渲染。渲染工作被分成 chunks:按单个路由段和Suspense Boundaries

每个 chunk 分两步渲染:

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

然后,在客户端上:

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

    什么事 React 服务器组件 Payload(RSC)?

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

    • 服务器组件的渲染结果
    • 客户端组件应呈现的位置的占位符以及对其 Javascript 文件的引用
    • 从服务器组件传递给客户端组件的任何 props

服务器渲染策略

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

Static Rendering (默认)

使用静态渲染,路由在构建时渲染,或者在数据重新验证之后在后台渲染。 结果被缓存,并可以被推送到 Content Delivery Network (CDN)。这种优化可以让您在用户和服务器请求之间共享渲染工作的结果。

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

Dynamic Rendering

通过动态渲染,可以在请求时为每个用户渲染路由。

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

带缓存数据的动态路由

在大多数网站中,路由不是完全静态的,也不是完全动态的 - 它是一个范围。例如,您可以拥有使用缓存的产品数据的电子商务页面(每隔一段时间重新验证一次),也可以有非缓存的个性化的客户数据。

在 Next.js 中, 您可以有动态渲染的路由,这些路由既包含缓存数据,又包含非缓存数据。这是因为 RSC Payload 和数据是分开缓存的。这使您可以选择动态渲染,而不必担心在请求时获取所有数据对性能的影响。

了解更多有关完整路由缓存数据缓存

切换到动态渲染

在渲染过程中, 如果发现dynamic functionuncached data request, Next.js 会切换到动态渲染整个路由。下表总结了动态函数和数据缓存如何影响路由是静态渲染还是动态渲染:

Dynamic FunctionsDataRoute
NoCachedStatically Rendered
YesCachedDynamically Rendered
NoNot CachedDynamically Rendered
YesNot CachedDynamically Rendered

在上表中,要使路由完全静态,必须缓存所有数据。不过,您可以有一个动态呈现的路由,它同时使用缓存和非缓存的数据获取。

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

Dynamic Functions

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

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

Streaming

Diagram showing parallelization of route segments during streaming, showing data fetching, rendering, and hydration of individual chunks.

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

Diagram showing partially rendered page on the client, with loading UI for chunks that are being streamed.

默认情况下,流是内置在 Next.js 应用路由器中的。这有助于提高初始页面加载性能,以及依赖于较慢的会阻碍整个路由呈现的数据获取的 UI。例如,产品页面上的评论。

您可以使用loading.js和使用React Suspense的 UI 组件开始流式传输路由段。参阅Loading UI and Streaming章节获取更多信息。