跳到内容

服务器组件

React 服务器组件允许你编写可以在服务器上渲染并选择性缓存的 UI。在 Next.js 中,渲染工作通过路由段进一步拆分,以实现流式处理和部分渲染,并且有三种不同的服务器渲染策略

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

服务器渲染的优势

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

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

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

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

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

在服务器上,Next.js 使用 React 的 API 来编排渲染。渲染工作被拆分为块:按单独的路由段和 Suspense 边界

每个块都分两步渲染

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

然后,在客户端

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

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

RSC Payload 是渲染的 React 服务器组件树的紧凑二进制表示形式。它被客户端上的 React 用于更新浏览器的 DOM。RSC Payload 包含

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

服务器渲染策略

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

静态渲染(默认)

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

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

动态渲染

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

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

具有缓存数据的动态路由

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

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

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

切换到动态渲染

在渲染期间,如果发现动态 API 或 fetch 选项 { cache: 'no-store' },Next.js 将切换到动态渲染整个路由。下表总结了动态 API 和数据缓存如何影响路由是静态渲染还是动态渲染

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

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

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

动态 API

动态 API 依赖于只能在请求时(而不是在预渲染期间提前)才能知道的信息。使用任何这些 API 都表示开发人员的意图,并将选择在请求时将整个路由动态渲染。这些 API 包括

流式处理

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 App Router 中。这有助于提高初始页面加载性能,以及依赖于较慢数据获取的 UI,这些数据获取会阻止渲染整个路由。例如,产品页面上的评论。

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

下一步

了解 Next.js 如何缓存数据和静态渲染的结果。