服务器组件
React 服务器组件允许你编写可以在服务器上渲染和选择性缓存的 UI。在 Next.js 中,渲染工作被路由段进一步分割,以实现流式渲染和部分渲染,并且存在三种不同的服务器渲染策略:
¥React Server Components allow you to write UI that can be rendered and optionally cached on the server. In Next.js, the rendering work is further split by route segments to enable streaming and partial rendering, and there are three different server rendering strategies:
本页将介绍服务器组件的工作原理、何时可能使用它们以及不同的服务器渲染策略。
¥This page will go through how Server Components work, when you might use them, and the different server rendering strategies.
服务器渲染的好处
¥Benefits of Server Rendering
在服务器上进行渲染工作有几个好处,包括:
¥There are a couple of benefits to doing the rendering work on the server, including:
-
数据获取:服务器组件允许你将数据获取移至更靠近数据源的服务器。这可以通过减少获取渲染所需数据所需的时间以及客户端需要发出的请求数量来提高性能。
¥Data Fetching: Server Components allow you to move data fetching to the server, closer to your data source. This can improve performance by reducing time it takes to fetch data needed for rendering, and the number of requests the client needs to make.
-
安全:服务器组件允许你将敏感数据和逻辑(例如令牌和 API 密钥)保留在服务器上,而不会有将它们暴露给客户端的风险。
¥Security: Server Components allow you to keep sensitive data and logic on the server, such as tokens and API keys, without the risk of exposing them to the client.
-
缓存:通过在服务器上渲染,结果可以被缓存并在后续请求和跨用户中重用。这可以通过减少每个请求上完成的渲染和数据获取量来提高性能并降低成本。
¥Caching: By rendering on the server, the result can be cached and reused on subsequent requests and across users. This can improve performance and reduce cost by reducing the amount of rendering and data fetching done on each request.
-
表现:服务器组件为你提供了额外的工具来优化基线性能。例如,如果你从完全由客户端组件组成的应用开始,将 UI 的非交互式部分移动到服务器组件可以减少所需的客户端 JavaScript 数量。这对于互联网速度较慢或设备功能较弱的用户来说是有益的,因为浏览器需要下载、解析和执行的客户端 JavaScript 较少。
¥Performance: Server Components give you additional tools to optimize performance from the baseline. For example, if you start with an app composed of entirely Client Components, moving non-interactive pieces of your UI to Server Components can reduce the amount of client-side JavaScript needed. This is beneficial for users with slower internet or less powerful devices, as the browser has less client-side JavaScript to download, parse, and execute.
-
初始页面加载和 首次内容绘制 (FCP):在服务器上,我们可以生成 HTML 以允许用户立即查看页面,而无需等待客户端下载、解析和执行渲染页面所需的 JavaScript。
¥Initial Page Load and First Contentful Paint (FCP): On the server, we can generate HTML to allow users to view the page immediately, without waiting for the client to download, parse and execute the JavaScript needed to render the page.
-
搜索引擎优化和社交网络共享性:搜索引擎机器人可以使用渲染的 HTML 来索引你的页面,社交网络机器人可以使用渲染的 HTML 来为你的页面生成社交卡预览。
¥Search Engine Optimization and Social Network Shareability: The rendered HTML can be used by search engine bots to index your pages and social network bots to generate social card previews for your pages.
-
流式:服务器组件允许你将渲染工作分成多个块,并在准备就绪时将它们流式传输到客户端。这允许用户更早地看到页面的某些部分,而不必等待整个页面在服务器上渲染。
¥Streaming: Server Components allow you to split the rendering work into chunks and stream them to the client as they become ready. This allows the user to see parts of the page earlier without having to wait for the entire page to be rendered on the server.
在 Next.js 中使用服务器组件
¥Using Server Components in Next.js
默认情况下,Next.js 使用服务器组件。这允许你自动实现服务器渲染,无需额外配置,并且你可以在需要时选择使用客户端组件,请参阅 客户端组件。
¥By default, Next.js uses Server Components. This allows you to automatically implement server rendering with no additional configuration, and you can opt into using Client Components when needed, see Client Components.
服务器组件是如何渲染的?
¥How are Server Components rendered?
在服务器上,Next.js 使用 React 的 API 来编排渲染。渲染工作被分成几个块:按个别路由段和 悬念边界。
¥On the server, Next.js uses React's APIs to orchestrate rendering. The rendering work is split into chunks: by individual route segments and Suspense Boundaries.
每个块都分两步渲染:
¥Each chunk is rendered in two steps:
-
React 将服务器组件渲染为一种特殊的数据格式,称为 React 服务器组件有效负载(RSC Payload)。
¥React renders Server Components into a special data format called the React Server Component Payload (RSC Payload).
-
Next.js 使用 RSC 有效负载和客户端组件 JavaScript 指令在服务器上渲染 HTML。
¥Next.js uses the RSC Payload and Client Component JavaScript instructions to render HTML on the server.
然后,在客户端:
¥Then, on the client:
-
HTML 用于立即显示路由的快速非交互式预览 - 这仅适用于初始页面加载。
¥The HTML is used to immediately show a fast non-interactive preview of the route - this is for the initial page load only.
-
React 服务器组件有效负载用于协调客户端和服务器组件树,并更新 DOM。
¥The React Server Components Payload is used to reconcile the Client and Server Component trees, and update the DOM.
-
JavaScript 指令用于 hydrate 客户端组件并使应用具有交互性。
¥The JavaScript instructions are used to hydrate Client Components and make the application interactive.
什么是 React 服务器组件负载 (RSC)?
¥What is the React Server Component Payload (RSC)?
RSC Payload 是渲染的 React Server 组件树的紧凑二进制表示。客户端上的 React 使用它来更新浏览器的 DOM。RSC 有效负载包含:
¥The RSC Payload is a compact binary representation of the rendered React Server Components tree. It's used by React on the client to update the browser's DOM. The RSC Payload contains:
Server Components 的渲染结果
¥The rendered result of Server Components
客户端组件应渲染的位置的占位符以及对其 JavaScript 文件的引用
¥Placeholders for where Client Components should be rendered and references to their JavaScript files
从服务器组件传递到客户端组件的任何属性
¥Any props passed from a Server Component to a Client Component
服务器渲染策略
¥Server Rendering Strategies
服务器渲染分为三个子集:静态、动态和流式。
¥There are three subsets of server rendering: Static, Dynamic, and Streaming.
静态渲染(默认)
¥Static Rendering (Default)
使用静态渲染,路由在构建时渲染,或者在 数据重新验证 之后在后台渲染。结果被缓存并可以推送到 内容分发网络 (CDN)。此优化允许你在用户和服务器请求之间共享渲染工作的结果。
¥With Static Rendering, routes are rendered at build time, or in the background after data revalidation. The result is cached and can be pushed to a Content Delivery Network (CDN). This optimization allows you to share the result of the rendering work between users and server requests.
当路由具有未针对用户个性化且可在构建时已知的数据(例如静态博客文章或产品页面)时,静态渲染非常有用。
¥Static rendering is useful when a route has data that is not personalized to the user and can be known at build time, such as a static blog post or a product page.
动态渲染
¥Dynamic Rendering
通过动态渲染,可以在请求时为每个用户渲染路由。
¥With Dynamic Rendering, routes are rendered for each user at request time.
当路由具有针对用户的个性化数据或具有仅在请求时才能知道的信息(例如 cookie 或 URL 的搜索参数)时,动态渲染非常有用。
¥Dynamic rendering is useful when a route has data that is personalized to the user or has information that can only be known at request time, such as cookies or the URL's search params.
具有缓存数据的动态路由
¥Dynamic Routes with Cached Data
在大多数网站中,路由不是完全静态或完全动态的 - 这是一个频谱。例如,你可以拥有一个电子商务页面,该页面使用定期重新验证的缓存产品数据,但也包含未缓存的个性化客户数据。
¥In most websites, routes are not fully static or fully dynamic - it's a spectrum. For example, you can have an e-commerce page that uses cached product data that's revalidated at an interval, but also has uncached, personalized customer data.
在 Next.js 中,你可以动态渲染包含缓存和未缓存数据的路由。这是因为 RSC 有效负载和数据是分开缓存的。这使你可以选择动态渲染,而不必担心在请求时获取所有数据对性能的影响。
¥In Next.js, you can have dynamically rendered routes that have both cached and uncached data. This is because the RSC Payload and data are cached separately. This allows you to opt into dynamic rendering without worrying about the performance impact of fetching all the data at request time.
¥Learn more about the full-route cache and Data Cache.
切换到动态渲染
¥Switching to Dynamic Rendering
在渲染过程中,如果发现 动态函数 或 未缓存的数据请求,Next.js 将切换为动态渲染整个路由。下表总结了动态函数和数据缓存如何影响静态或动态渲染路由:
¥During rendering, if a dynamic function or uncached data request is discovered, Next.js will switch to dynamically rendering the whole route. This table summarizes how dynamic functions and data caching affect whether a route is statically or dynamically rendered:
动态函数 | 数据 | 路由 |
---|---|---|
不 | 缓存 | 静态渲染 |
是的 | 缓存 | 动态渲染 |
不 | 未缓存 | 动态渲染 |
是的 | 未缓存 | 动态渲染 |
在上表中,要使路由完全静态,必须缓存所有数据。但是,你可以拥有使用缓存和未缓存数据获取的动态渲染路由。
¥In the table above, for a route to be fully static, all data must be cached. However, you can have a dynamically rendered route that uses both cached and uncached data fetches.
作为开发者,你无需在静态渲染和动态渲染之间进行选择,因为 Next.js 会根据所使用的功能和 API 自动为每个路由选择最佳渲染策略。相反,你可以选择何时执行 缓存或重新验证特定数据,并且可以选择执行 UI 的 stream 部分。
¥As a developer, you do not need to choose between static and dynamic rendering as Next.js will automatically choose the best rendering strategy for each route based on the features and APIs used. Instead, you choose when to cache or revalidate specific data, and you may choose to stream parts of your UI.
动态函数
¥Dynamic Functions
动态函数依赖于只能在请求时获知的信息,例如用户的 cookie、当前请求标头或 URL 的搜索参数。在 Next.js 中,这些动态函数是:
¥Dynamic functions rely on information that can only be known at request time such as a user's cookies, current requests headers, or the URL's search params. In Next.js, these dynamic functions are:
-
cookies()
和headers()
:在服务器组件中使用这些将在请求时选择整个路由进行动态渲染。¥**
cookies()
andheaders()
**: Using these in a Server Component will opt the whole route into dynamic rendering at request time. -
searchParams
:在 页面 上使用searchParams
属性将选择页面在请求时进行动态渲染。¥**
searchParams
**: Using thesearchParams
prop on a Page will opt the page into dynamic rendering at request time.
使用这些函数中的任何一个都会在请求时选择整个路由进行动态渲染。
¥Using any of these functions will opt the whole route into dynamic rendering at request time.
流式
¥Streaming
流式传输使你能够从服务器逐步渲染 UI。工作被分成多个块,并在准备就绪时流式传输到客户端。这允许用户在整个内容完成渲染之前立即看到页面的部分内容。
¥Streaming enables you to progressively render UI from the server. Work is split into chunks and streamed to the client as it becomes ready. This allows the user to see parts of the page immediately, before the entire content has finished rendering.
默认情况下,流式传输内置于 Next.js App Router 中。这有助于提高初始页面加载性能,以及依赖于较慢数据获取(会阻止渲染整个路由)的 UI。例如,产品页面上的评论。
¥Streaming is built into the Next.js App Router by default. This helps improve both the initial page loading performance, as well as UI that depends on slower data fetches that would block rendering the whole route. For example, reviews on a product page.
你可以使用 loading.js
开始流式传输路由段,并使用 React Suspense 开始流式传输 UI 组件。有关详细信息,请参阅 加载 UI 和流式传输 部分。
¥You can start streaming route segments using loading.js
and UI components with React Suspense. See the Loading UI and Streaming section for more information.