服务端组件 (Server Components)

React 服务端组件 (Server Components) 允许您编写可在服务端渲染并选择性缓存的 UI。在 Next.js 中,渲染工作会按路由段进一步拆分以实现流式传输和部分渲染,并提供三种不同的服务端渲染策略:

本页将介绍服务端组件的工作原理、适用场景以及不同的服务端渲染策略。

服务端渲染的优势

在服务端执行渲染工作具有以下优势:

  • 数据获取:服务端组件让您能将数据获取移至更靠近数据源的服务端,通过减少渲染所需数据的获取时间和客户端请求次数来提升性能。
  • 安全性:敏感数据和逻辑(如令牌和 API 密钥)可保留在服务端,避免暴露给客户端。
  • 缓存:服务端渲染结果可被缓存并复用于后续请求和不同用户,通过减少每次请求的渲染和数据获取量来提升性能并降低成本。
  • 性能优化:服务端组件提供额外工具突破性能基线。例如将非交互式 UI 移至服务端组件可减少客户端 JavaScript 体积,这对网络较慢或设备性能较低的用户尤为有益。
  • 初始页面加载与首次内容绘制 (FCP):服务端生成 HTML 让用户无需等待客户端下载、解析和执行 JavaScript 即可立即查看页面。
  • 搜索引擎优化与社交分享:渲染后的 HTML 可供搜索引擎爬虫索引页面,社交网络爬虫生成页面预览卡片。
  • 流式传输:服务端组件允许将渲染工作分块并逐步流式传输至客户端,让用户无需等待整个页面完成渲染即可提前看到部分内容。

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

Next.js 默认使用服务端组件,无需额外配置即可自动实现服务端渲染。您也可以根据需要选择使用客户端组件 (Client Components)

服务端组件如何渲染?

在服务端,Next.js 使用 React API 协调渲染工作。渲染任务被拆分为多个块:按独立路由段和 Suspense 边界 (Suspense Boundaries) 划分。

每个块的渲染分为两步:

  1. React 将服务端组件渲染为特殊数据格式 React 服务端组件载荷 (RSC Payload)
  2. Next.js 使用 RSC 载荷和客户端组件 JavaScript 指令在服务端渲染 HTML

在客户端则分为三步:

  1. 使用 HTML 立即显示路由的快速非交互式预览(仅限初始页面加载)
  2. 使用 React 服务端组件载荷协调客户端与服务端组件树,并更新 DOM
  3. 使用 JavaScript 指令水合 (hydrate) 客户端组件并使应用具备交互性

什么是 React 服务端组件载荷 (RSC)?

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

  • 服务端组件的渲染结果
  • 客户端组件渲染位置的占位符及其 JavaScript 文件引用
  • 从服务端组件传递给客户端组件的所有 props

服务端渲染策略

服务端渲染分为三种子类型:静态渲染、动态渲染和流式传输。

静态渲染(默认)

通过静态渲染,路由会在构建时或在数据重新验证后在后台渲染。结果会被缓存并可推送至内容分发网络 (CDN),使得渲染结果可在用户和服务器请求间共享。

静态渲染适用于包含非用户个性化数据且构建时已知的路由,如静态博客文章或产品页面。

动态渲染

通过动态渲染,路由会在请求时为每个用户单独渲染。

动态渲染适用于包含用户个性化数据或只能在请求时获取信息(如 cookies 或 URL 搜索参数)的路由。

使用缓存数据的动态路由

大多数网站的路由并非完全静态或动态,而是介于两者之间。例如电商页面可能使用定期重新验证的缓存产品数据,同时也包含非缓存的用户个性化数据。

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

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

切换至动态渲染

在渲染过程中,如果检测到动态函数非缓存数据请求,Next.js 会切换为动态渲染整个路由。下表总结了动态函数和数据缓存如何影响路由渲染方式:

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

上表中,要使路由完全静态化,所有数据必须被缓存。但动态渲染的路由可以同时使用缓存和非缓存数据。

开发者无需手动选择静态或动态渲染,Next.js 会根据使用的功能和 API 自动为每个路由选择最佳策略。您只需决定何时缓存或重新验证特定数据,并可以选择流式传输部分 UI。

动态函数

动态函数依赖只能在请求时获取的信息,如用户 cookies、当前请求头或 URL 搜索参数。在 Next.js 中,这些动态函数包括:

  • cookies()headers():在服务端组件中使用会使整个路由在请求时转为动态渲染。
  • searchParams:在 Page 组件上使用 searchParams 属性会使页面在请求时转为动态渲染。

使用以上任意函数都会使整个路由在请求时转为动态渲染。

流式传输

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

流式传输允许您从服务端渐进式渲染 UI。工作被拆分为多个块,并在准备就绪后流式传输至客户端。这让用户能在全部内容完成渲染前立即看到部分页面。

客户端部分渲染页面示意图,显示正在流式传输的块的加载状态

流式传输已内置在 Next.js 应用路由中。这既提升了初始页面加载性能,也优化了依赖较慢数据请求的 UI 渲染(例如产品页面的评价部分)。

您可以通过 loading.jsReact Suspense 组件实现路由段的流式传输。详见加载状态与流式传输章节。

On this page