跳到主要内容

服务器组件

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

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

服务器渲染的好处

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

  • 数据获取:服务器组件允许您将数据获取移到服务器上,靠近您的数据源。这可以通过减少用于渲染所需数据的获取时间以及客户端需要进行的请求次数来提高性能。
  • 安全性:服务器组件允许您将敏感数据和逻辑保留在服务器上,例如令牌和API密钥,而无需将其风险暴露给客户端。
  • 缓存:通过在服务器上进行渲染,结果可以被缓存并在后续请求和用户之间重复使用。这可以通过减少每个请求上的渲染和数据获取量来提高性能并减少成本。
  • 捆绑大小:服务器组件允许您将以前可能影响客户端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指令来使客户端组件水合并使应用程序可交互。

什么是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中,这些动态函数包括:

  • cookies()headers():在服务器组件中使用这些函数将使整个路由在请求时切换到动态渲染。
  • useSearchParams()
    • 在客户端组件中,它会跳过静态渲染,而是在客户端上渲染到最近的父Suspense边界上的所有客户端组件。
    • 我们建议将使用useSearchParams()的客户端组件包装在<Suspense/>边界中。这将允许其上面的任何客户端组件被静态渲染。示例。
  • searchParams:使用Pages prop将页面切换到在请求时动态渲染。 使用这些函数之一将使整个路由在请求时切换到动态渲染。

流式传输

sequential parallel data fetching

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

server rendering with streaming

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

您可以使用loading.js和具有React Suspense 的UI组件开始流式]传输路由片段。 有关更多信息,请参见Loading UI and Streaming部分。