Introduction
什么是 Next.js?
Next.js 是一个用于构建 Web 应用程序的框架。
借助 Next.js,您可以使用 React 组件构建用户界面。然后,Next.js 为您的应用程序提供额外的结构、功能和优化。
在幕后,Next.js 还为您抽象和自动配置工具,如捆绑、编译等(bundling, compiling, and more.)。这使您可以专注于构建应用程序,而不是花时间设置工具。
无论您是个人开发人员还是大型团队的一员,Next.js 都可以帮助您构建交互式、动态且快速的 Web 应用程序。
主要特点
Feature | Description |
---|---|
Routing | A file-system based router built on top of Server Components that supports layouts, nested routing, loading states, error handling, and more.一个基于文件系统的路由器,建立在服务器组件之上,支持布局、嵌套路由、加载状态、错误处理等。 |
Rendering | Client-side and Server-side Rendering with Client and Server Components. Further optimized with Static and Dynamic Rendering on the server with Next.js. Streaming on Edge and Node.js runtimes.使用客户端和服务器组件的客户端和服务器端呈现。使用Next.js在服务器上进一步优化了静态和动态渲染。在Edge和Node.js运行时上流式传输。 |
Data Fetching | Simplified data fetching with async/await support in React Components and the fetch() s API that aligns with React and the Web Platform.在React组件中使用async/await支持简化数据获取,并且fetch() API与React和Web平台保持一致。 |
Styling | Support for your preferred styling methods, including CSS Modules, Tailwind CSS, and CSS-in-JS |
Optimizations | Improved Image Component with native browser lazy loading. New Font Module with automatic font optimization.改进的图像组件与本地浏览器延迟加载。新的字体模块与自动字体优化。 |
Typescript | Improved support for TypeScript, with better type checking and more efficient compilation, as well as support for optional chaining and nullish coalescing. 改进了对TypeScript的支持,具有更好的类型检查和更高效的编译,以及对可选链接和空合并的支持。 |
API Reference | Updates to the API design throughout Next.js. Please refer to the API Reference Section for new APIs.更新了整个Next.js的API设计。有关新的API,请参阅API参考部分。 |
如何使用这些文档
文档的章节和页面按顺序组织,从基础到高级,因此您可以在构建 Next.js 应用程序时逐步遵循它们。但是,您可以按任何顺序阅读它们或跳到适用于您的用例的页面。
在页面的右侧,您会看到一个目录,可以更轻松地在页面的各个部分之间导航。页面顶部的面包屑还会指示您是在查看 App Router 文档还是 Pages Router 文档。
To get started, checkout the Installation. If you're new to React or Server Components, we recommend reading the React Essentials page. 要开始,请检查安装。如果您是 React 或服务器组件的新手,我们建议您阅读 React Essentials 页面。
先决知识
尽管我们的文档旨在对初学者友好,但我们需要建立一个基线,以便文档可以专注于 Next.js 的功能。每当我们引入新概念时,我们都会确保提供相关文档的链接。
要充分利用我们的文档,建议您对 HTML、CSS 和 React 有基本的了解。如果您需要复习 React 技能,请查看以下资源:
辅助功能
为了在阅读文档时使用屏幕阅读器获得最佳的可访问性,我们建议使用 Firefox 和 NVDA,或者 Safari 和 VoiceOver。
If you have questions about anything related to Next.js, you're always welcome to ask our community on GitHub Discussions, Discord, Twitter, and Reddit.
React Essentials
要使用Next.js构建应用程序,熟悉React的新特性(如Server Components)会有所帮助。本页将介绍服务器和客户端组件之间的区别、何时使用它们以及推荐的模式。
如果你是React的新手,我们还建议你参考React文档。这里有一些很棒的学习资源:
Server Components
服务器和客户端组件允许开发人员构建跨服务器和客户端的应用程序,将客户端应用程序的丰富交互性与传统服务器呈现的改进性能相结合。
Thinking in Server Components
与React改变了我们构建ui的方式类似,React服务器组件引入了一种新的心智模型,用于构建利用服务器和客户端的混合应用程序。
React不再呈现整个应用程序的客户端(比如单页应用程序),而是让你可以根据组件的用途灵活地选择在哪里呈现组件。
For example, consider a page in your application: 例如,考虑应用程序中的一个页面:
如果我们将页面拆分为更小的组件,您将注意到大多数组件是非交互式的,并且可以作为服务器组件在服务器上呈现。对于较小的交互式UI,我们可以使用客户端组件。这与Next.js服务器优先的方法是一致的。
Why Server Components?
因此,您可能会想,为什么要使用服务器组件?与客户端组件相比,使用它们有什么优势?
服务器组件允许开发人员更好地利用服务器基础设施。例如,以前会影响客户端JavaScript包大小的大型依赖项可以完全保留在服务器上,从而提高性能。它们使编写React应用程序感觉类似于PHP或Ruby on Rails,但具有React的强大和灵活性以及用于模板UI的组件模型。
使用服务器组件,初始页面加载速度更快,并且减少了客户端JavaScript包的大小。基本客户端运行时的大小是可缓存和可预测的,并且不会随着应用程序的增长而增加。只有在通过客户端组件在应用程序中使用客户端交互时,才会添加额外的JavaScript。
当用Next.js加载路由时,初始HTML就会在服务器端呈现。然后这个HTML在浏览器中逐渐增强,允许客户端接管应用程序并添加交互性,通过异步加载Next.js和React客户端运行时。
To make the transition to Server Components easier, all components inside the App Router are Server Components by default, including special files and colocated components. This allows you to automatically adopt them with no extra work, and achieve great performance out of the box. You can also optionally opt-in to Client Components using the 'use client' directive.
为了更容易过渡到服务器组件,App Router中的所有组件默认都是服务器组件,包括特殊文件和配置的组件。这允许您自动采用它们,而不需要额外的工作,并获得开箱即用的出色性能。你也可以通过“use Client”指令选择加入客户端组件。
Client Components
Client Components enable you to add client-side interactivity to your application. In Next.js, they are pre-rendered on the server and hydrated on the client. You can think of Client Components as how components in the Pages Router have always worked.
客户端组件使您能够向应用程序添加客户端交互性。在Next.js中,它们在服务器上预渲染,并在客户端上进行渲染。您可以将客户端组件视为Pages Router中的组件一直以来的工作方式。
The "use client" directive
“use client”指令是一种约定,用于声明服务器组件和客户端组件模块图之间的边界。
'use client';
import { useState } from 'react';
export default function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>Click me</button>
</div>
);
}
“使用客户端”位于仅服务器和客户端代码之间。它被放置在文件的顶部,在导入的上方,以定义从仅服务器部分到客户机部分的边界的分界点。一旦在文件中定义了“use client”,导入其中的所有其他模块,包括子组件,都被视为客户端包的一部分。
Since Server Components are the default, all components are part of the Server Component module graph unless defined or imported in a module that starts with the "use client"
directive.
由于服务器组件是默认的,所以所有组件都是服务器组件模块图的一部分,除非在以“use client”指令开头的模块中定义或导入。
Good to know:
- Components in the Server Component module graph are guaranteed to be only rendered on the server.
- Components in the Client Component module graph are primarily rendered on the client, but with Next.js, they can also be pre-rendered on the server and hydrated on the client.
- The
"use client"
directive must be defined at the top of a file before any imports. "use client"
does not need to be defined in every file. The Client module boundary only needs to be defined once, at the "entry point", for all modules imported into it to be considered a Client component.
Server Component模块图中的组件保证只在服务器上呈现。
Client Component模块图中的组件主要在客户端上呈现,但是使用Next.js,它们也可以在服务器上预呈现,并在客户端上进行渲染。
在任何导入之前,必须在文件的顶部定义“use client”指令。
“use client”不需要在每个文件中都定义。客户端模块边界只需要在“入口点”定义一次,所有导入到其中的模块都被视为客户端组件。
When to use Server and Client Components?
为了简化在服务器组件和客户端组件之间的选择,我们建议使用服务器组件(默认在app目录中),直到你有了客户端组件的用例。
下表总结了服务器和客户端组件的不同用例:
What do you need to do? | Server Component | Client Component |
---|---|---|
Fetch data. | √ | × |
Access backend resources (directly) | √ | × |
Keep sensitive information on the server (access tokens, API keys, etc) | √ | × |
Keep large dependencies on the server / Reduce client-side JavaScript | √ | × |
Add interactivity and event listeners (onClick() , onChange() , etc) | × | √ |
Use State and Lifecycle Effects (useState() , useReducer() , useEffect() , etc) | × | √ |
Use browser-only APIs | × | √ |
Use custom hooks that depend on state, effects, or browser-only APIs | × | √ |
Use React Class components | × | √ |
Patterns
Moving Client Components to the Leaves
为了提高应用程序的性能,我们建议尽可能将客户端组件移动到组件树的叶子位置。
例如,你可能有一个布局,它有静态元素(如logo,链接等)和一个使用状态的交互式搜索栏。
与其把整个布局做成一个客户端组件,不如把交互逻辑移到一个客户端组件(例如<SearchBar />
),并保持你的布局作为一个服务器组件。这意味着您不必将布局的所有Javascript组件发送到客户端。
app/layout.tsx
// SearchBar is a Client Component
import SearchBar from './searchbar';
// Logo is a Server Component
import Logo from './logo';
// Layout is a Server Component by default
export default function Layout({
children,
}: {
children: React.ReactNode;
}) {
return (
<>
<nav>
<Logo />
<SearchBar />
</nav>
<main>{children}</main>
</>
);
}
Composing Client and Server Components
服务器组件和客户端组件可以组合在同一个组件树中。
在幕后,React处理渲染如下:
-
On the server, React renders all Server Components before sending the result to the client.
- This includes Server Components nested inside Client Components.
- Client Components encountered during this stage are skipped.
-
On the client, React renders Client Components and slots in the rendered result of Server Components, merging the work done on the server and client.
- If any Server Components are nested inside a Client Component, their rendered content will be placed correctly within the Client Component.
在服务器端,React在将结果发送给客户端之前呈现所有服务器组件。
- 这包括嵌套在客户端组件中的服务器组件。
- 跳过此阶段遇到的客户端组件。
在客户端,React呈现客户端组件,并在服务器组件的呈现结果中插入插槽,合并在服务器和客户端上完成的工作。
- 如果任何服务器组件嵌套在客户端组件中,它们呈现的内容将被正确地放置在客户端组件中。
Good to know: In Next.js, during the initial page load, both the rendered result of Server Components from the above step and Client components are pre-rendered on the server as HTML to produce a faster initial page load
值得注意的是:在Next.js中,在初始页面加载期间,上述步骤中服务器组件和客户端组件的呈现结果都在服务器上预呈现为HTML,以产生更快的初始页面加载。
Nesting Server Components inside Client Components
鉴于上面概述的呈现流,将服务器组件导入到客户端组件有一个限制,因为这种方法需要额外的服务器往返。
Unsupported Pattern
不支持以下模式。你不能将服务器组件导入到客户端组件中:
app/example-client-component.tsx
'use client';
// This pattern will **not** work!
// You cannot import a Server Component into a Client Component.
import ExampleServerComponent from './example-server-component';
export default function ExampleClientComponent({
children,
}: {
children: React.ReactNode;
}) {
const [count, setCount] = useState(0);
return (
<>
<button onClick={() => setCount(count + 1)}>{count}</button>
<ExampleServerComponent />
</>
);
}
Recommended Pattern: Passing Server Components to Client Components as Props
推荐模式:将服务器组件作为 props 传递给客户端组件
相反,在设计客户端组件时,你可以使用React props来标记服务器组件的“漏洞”。
服务器组件将在服务器上呈现,当客户端组件在客户端上呈现时,“洞”将被服务器组件的呈现结果填充。
一个常见的模式是使用React的children属性来创建“洞”。我们可以重构<ExampleClientComponent />
以接受一个通用的子组件,并将<ExampleClientComponent />
的导入和显式嵌套移动到父组件。
app/example-client-component.tsx
'use client';
import { useState } from 'react';
export default function ExampleClientComponent({
children,
}: {
children: React.ReactNode;
}) {
const [count, setCount] = useState(0);
return (
<>
<button onClick={() => setCount(count + 1)}>{count}</button>
{children}
</>
);
}
现在,<ExampleClientComponent>
不知道 children 是什么。事实上,从它的角度来看,它甚至不知道子项最终将由服务器组件的结果填充。
ExampleClientComponent
的唯一责任是决定最终应该放置的任何子项。
在父服务器组件中,您可以导入 <ExampleClientComponent>
和 <ExampleServerComponent>
并将 <ExampleServerComponent>
作为 <ExampleClientComponent>
的子项传递:
app/page.tsx
// This pattern works:
// You can pass a Server Component as a child or prop of a
// Client Component.
import ExampleClientComponent from './example-client-component';
import ExampleServerComponent from './example-server-component';
// Pages in Next.js are Server Components by default
export default function Page() {
return (
<ExampleClientComponent>
<ExampleServerComponent />
</ExampleClientComponent>
);
}
通过这种方法,<ExampleClientComponent>
和<ExampleServerComponent>
的呈现是解耦的,可以独立呈现——与服务器组件保持一致,服务器组件在客户端组件之前呈现在服务器上。
Good to know
-
This pattern is already applied in layouts and pages with the
children
prop so you don't have to create an additional wrapper component. -
Passing React components (JSX) to other components is not a new concept and has always been part of the React composition model.
-
This composition strategy works across Server and Client components because the component that receives the prop has no knowledge of what the prop is. It is only responsible for where the thing that it is passed should be placed.
- This allows the passed prop to be rendered independently, in this case, on the server, well before the Client Component is rendered on the client.
- The very same strategy of "lifting content up" has been used to avoid state changes in a parent component re-rendering an imported nested child component.
-
You're not limited to the
children
prop. You can use any prop to pass JSX.
此模式已经应用于具有children属性的布局和页面中,因此您不必创建额外的包装器组件。
将React组件(JSX)传递给其他组件并不是一个新概念,并且一直是React组合模型的一部分。
这种组合策略可以跨Server和Client组件工作,因为接收props
的组件不知道props
是什么。它只负责它所传递的东西应该放在哪里。
这允许在客户端渲染客户端组件之前,在服务器上独立渲染传递的prop。
同样的“提升内容”策略也被用来避免父组件中的状态改变,从而重新呈现导入的嵌套子组件。
Passing props from Server to Client Components (Serialization)
Props passed from the Server to Client components need to be serializable. This means that values such as functions, Dates, etc, cannot be passed directly to client components.
从服务器传递到客户端组件的道具需要是可序列化的。这意味着函数、日期等值不能直接传递给客户端组件。
Where is the Network Boundary?
在 App Router 中,网络边界位于 Server Components 和 Client Components 之间。这与边界位于 getStaticProps/getServerSideProps 和页面组件之间的页面不同。服务器组件内部获取的数据不需要序列化,因为它不会跨越网络边界,除非它被传递给客户端组件。了解有关使用服务器组件获取数据的更多信息。
Keeping Server-Only Code out of Client Components (Poisoning)
由于 JavaScript 模块可以在服务器和客户端组件之间共享,因此原本只打算在服务器上运行的代码有可能偷偷进入客户端。
例如,采用以下数据获取功能:
lib/data.ts
export async function getData() {
const res = await fetch('https://external-service.com/data', {
headers: {
authorization: process.env.API_KEY,
},
});
return res.json();
}
乍一看,getData 似乎同时适用于服务器和客户端。但是因为环境变量 API_KEY 没有 NEXT_PUBLIC 前缀,所以它是一个私有变量,只能在服务器上访问。 Next.js 在客户端代码中将私有环境变量替换为空字符串,以防止泄露安全信息。
因此,即使可以在客户端导入并执行 getData(),它也不会按预期工作。虽然公开变量会使函数在客户端上运行,但它会泄露敏感信息。
因此,编写此函数的意图是它只会在服务器上执行。
The "server only" package
为了防止这种客户端无意识地使用服务器代码,我们可以使用 server-only 包来给其他开发人员一个构建时错误,如果他们不小心将这些模块之一导入客户端组件。
要仅使用服务器,请先安装软件包:
npm install server-only
然后将包导入任何包含仅服务器代码的模块:
lib/data.js
import 'server-only';
export async function getData() {
const res = await fetch('https://external-service.com/data', {
headers: {
authorization: process.env.API_KEY,
},
});
return res.json();
}
Now, any Client Component that imports getData()
will receive a build-time error explaining that this module can only be used on the server.
现在,任何导入 getData() 的客户端组件都会收到一个构建时错误,说明该模块只能在服务器上使用。
The corresponding package client-only
can be used to mark modules that contain client-only code – for example, code that accesses the window
object.
相应的包 client-only 可用于标记包含仅客户端代码的模块——例如,访问窗口对象的代码。
Data Fetching
虽然可以在客户端组件中获取数据,但我们建议在服务器组件中获取数据,除非您有特定原因需要在客户端获取数据。将数据提取移动到服务器可以带来更好的性能和用户体验。
Learn more about data fetching.
Third-party packages
由于服务器组件是新的,生态系统中的第三方包才刚刚开始向使用仅客户端功能(如 useState、useEffect 和 createContext)的组件添加“使用客户端”指令。
今天,许多使用仅客户端功能的 npm 包中的组件还没有该指令。这些第三方组件将在您自己的客户端组件中按预期工作,因为它们具有“使用客户端”指令,但它们不会在服务器组件中工作。
例如,假设您已经安装了假设的 acme-carousel 包,它有一个 组件。该组件使用 useState,但还没有“使用客户端”指令。
如果您在客户端组件中使用 <AcmeCarousel />
,它将按预期工作:
app/gallery.tsx
'use client';
import { useState } from 'react';
import { AcmeCarousel } from 'acme-carousel';
export default function Gallery() {
let [isOpen, setIsOpen] = useState(false);
return (
<div>
<button onClick={() => setIsOpen(true)}>View pictures</button>
{/* 🟢 Works, since AcmeCarousel is used within a Client Component */}
{isOpen && <AcmeCarousel />}
</div>
);
}
但是,如果您尝试在服务器组件中直接使用它,您会看到一个错误:
app/page.tsx
import { AcmeCarousel } from 'acme-carousel';
export default function Page() {
return (
<div>
<p>View pictures</p>
{/* 🔴 Error: `useState` can not be used within Server Components */}
<AcmeCarousel />
</div>
);
}
这是因为 Next.js 不知道 <AcmeCarousel />
正在使用仅限客户端的功能。
要解决此问题,您可以将依赖于仅客户端功能的第三方组件包装在您自己的客户端组件中:
app/carousel.tsx
'use client';
import { AcmeCarousel } from 'acme-carousel';
export default AcmeCarousel;
现在,您可以直接在服务器组件中使用 <Carousel />
:
app/page.tsx
import Carousel from './carousel';
export default function Page() {
return (
<div>
<p>View pictures</p>
{/* 🟢 Works, since Carousel is a Client Component */}
<Carousel />
</div>
);
}
We don't expect you to need to wrap most third-party components since it's likely you'll be using them within Client Components. However, one exception is provider components, since they rely on React state and context, and are typically needed at the root of an application. Learn more about third-party context providers below.
我们不希望您需要包装大多数第三方组件,因为您很可能会在客户端组件中使用它们。然而,一个例外是提供者组件,因为它们依赖于 React 状态和上下文,并且通常在应用程序的根部需要。在下面了解有关第三方上下文提供程序的更多信息。
Library Authors
以类似的方式,创建供其他开发人员使用的包的库作者可以使用“use client”指令来标记其包的客户端入口点。这允许包的用户将包组件直接导入到他们的服务器组件中,而不必创建包装边界。
-
You can optimize your package by using 'use client' deeper in the tree, allowing the imported modules to be part of the Server Component module graph.
-
您可以通过在树的更深处使用“使用客户端”来优化您的包,允许导入的模块成为服务器组件模块图的一部分。
-
It's worth noting some bundlers might strip out
"use client"
directives. You can find an example of how to configure esbuild to include the"use client"
directive in the React Wrap Balancer and Vercel Analytics repositories.
值得注意的是,一些打包器可能会去掉“使用客户端”指令。你可以在React Wrap Balancer和Vercel Analytics存储库中找到一个如何配置esbuild以包含“use client”指令的示例。
Context
Most React applications rely on context to share data between components, either directly via createContext
, or indirectly via provider components imported from third-party libraries.
大多数React应用依赖上下文在组件之间共享数据,要么直接通过createContext,要么间接通过从第三方库导入的提供商组件。
In Next.js 13, context is fully supported within Client Components, but it cannot be created or consumed directly within Server Components. This is because Server Components have no React state (since they're not interactive), and context is primarily used for rerendering interactive components deep in the tree after some React state has been updated.
在 Next.js 13 中,客户端组件完全支持上下文,但不能直接在服务器组件中创建或使用它。这是因为服务器组件没有 React 状态(因为它们不是交互式的),并且上下文主要用于在某些 React 状态更新后重新呈现树深处的交互式组件。
We'll discuss alternatives for sharing data between Server Components, but first, let's take a look at how to use context within Client Components.
我们将讨论在服务器组件之间共享数据的备选方案,但首先让我们看一下如何在客户端组件中使用上下文。
All of the context APIs are fully supported within Client Components:
客户端组件完全支持所有上下文 API:
app/sidebar.tsx
'use client';
import { createContext, useContext, useState } from 'react';
const SidebarContext = createContext();
export function Sidebar() {
const [isOpen, setIsOpen] = useState();
return (
<SidebarContext.Provider value={{ isOpen }}>
<SidebarNav />
</SidebarContext.Provider>
);
}
function SidebarNav() {
let { isOpen } = useContext(SidebarContext);
return (
<div>
<p>Home</p>
{isOpen && <Subnav />}
</div>
);
}
However, context providers are typically rendered near the root of an application to share global concerns, like the current theme. Because context is not supported in Server Components, trying to create a context at the root of your application will cause an error:
但是,上下文提供程序通常呈现在应用程序的根附近以共享全局关注点,例如当前主题。由于服务器组件不支持上下文,因此尝试在应用程序的根目录下创建上下文会导致错误:
app/layout.tsx
import { createContext } from 'react';
// 🔴 createContext is not supported in Server Components
export const ThemeContext = createContext({});
export default function RootLayout({ children }) {
return (
<html>
<body>
<ThemeContext.Provider value="dark">{children}</ThemeContext.Provider>
</body>
</html>
);
}
To fix this, create your context and render its provider inside of a Client Component:
要解决此问题,请创建您的上下文并在客户端组件中呈现其提供者:
app/theme-provider.tsx
'use client';
import { createContext } from 'react';
export const ThemeContext = createContext({});
export default function ThemeProvider({ children }) {
return
<ThemeContext.Provider value="dark">
{children}
</ThemeContext.Provider>;
}
Your Server Component will now be able to directly render your provider since it's been marked as a Client Component:
您的服务器组件现在可以直接呈现您的提供者,因为它已被标记为客户端组件:
app/layout.tsx
import ThemeProvider from './theme-provider';
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html>
<body>
<ThemeProvider>{children}</ThemeProvider>
</body>
</html>
);
}
With the provider rendered at the root, all other Client Components throughout your app will be able to consume this context.
通过在根节点呈现该提供商,应用中的所有其他客户端组件都可以使用该上下文。
Note: You should render providers as deep as possible in the tree – notice how ThemeProvider
only wraps {children}
instead of the entire <html>
document. This makes it easier for Next.js to optimize the static parts of your Server Components.
注意:您应该在树中尽可能深地呈现提供者——注意 ThemeProvider 如何仅包装 {children} 而不是整个 文档。这使 Next.js 更容易优化服务器组件的静态部分。
Rendering third-party context providers in Server Components
Third-party npm packages often include Providers that need to be rendered near the root of your application. If these providers include the "use client"
directive, they can be rendered directly inside of your Server Components. However, since Server Components are so new, many third-party providers won't have added the directive yet.
第三方 npm 包通常包含需要在应用程序根目录附近呈现的提供程序。如果这些提供者包含“使用客户端”指令,则它们可以直接在您的服务器组件内呈现。但是,由于服务器组件非常新,许多第三方提供商还没有添加该指令。
If you try to render a third-party provider that doesn't have "use client"
, it will cause an error:
如果您尝试呈现没有“使用客户端”的第三方提供程序,则会导致错误:
app/layout.tsx
import { ThemeProvider } from 'acme-theme';
export default function RootLayout({ children }) {
return (
<html>
<body>
{/* 🔴 Error: `createContext` can't be used in Server Components */}
<ThemeProvider>{children}</ThemeProvider>
</body>
</html>
);
}
To fix this, wrap third-party providers in your own Client Component:
要解决此问题,请将第三方提供商包装在您自己的客户端组件中:
app/providers.js
'use client';
import { ThemeProvider } from 'acme-theme';
import { AuthProvider } from 'acme-auth';
export function Providers({ children }) {
return (
<ThemeProvider>
<AuthProvider>{children}</AuthProvider>
</ThemeProvider>
);
}
Now, you can import and render <Providers />
directly within your root:
现在,您可以直接在根目录中导入和呈现 <Providers />
:
import { Providers } from './providers';
export default function RootLayout({ children }) {
return (
<html>
<body>
<Providers>{children}</Providers>
</body>
</html>
);
}
With the providers rendered at the root, all the components and hooks from these libraries will work as expected within your own Client Components.
通过在根目录中呈现提供程序,这些库中的所有组件和挂钩都将在您自己的客户端组件中按预期工作。
Once a third-party library has added "use client"
to its client code, you'll be able to remove the wrapper Client Component.
一旦第三方库将“使用客户端”添加到其客户端代码中,您就可以删除包装客户端组件。
Sharing data between Server Components
在服务器组件之间共享数据
Since Server Components are not interactive and therefore do not read from React state, you don't need the full power of context to share data. You can use native JavaScript patterns like global singletons within module scope if you have common data that multiple Server Component need to access.
由于服务器组件不是交互式的,因此不会从 React 状态读取,因此您不需要上下文的全部功能来共享数据。如果您有多个服务器组件需要访问的公共数据,您可以在模块范围内使用本地 JavaScript 模式,如全局单例。
For example, a module can be used to share a database connection across multiple components:
例如,一个模块可用于跨多个组件共享数据库连接:
utils/database.ts
export const db = new DatabaseConnection(...);
app/users/layout.tsx
import { db } from "@utils/database";
export async function UsersLayout() {
let users = await db.query(...);
// ...
}
app/users/[id]/page.tsx
import { db } from "@utils/database";
export async function DashboardPage() {
let user = await db.query(...);
// ...
}
In the above example, both the layout and page need to make database queries. Each of these components shares access to the database by importing the @utils/database
module.
在上面的例子中,布局和页面都需要进行数据库查询。这些组件中的每一个都通过导入 @utils/database 模块来共享对数据库的访问。
Sharing fetch requests between Server Components
在服务器组件之间共享获取请求
When fetching data, you may want to share the result of a fetch
between a page
or layout
and some of its children components. This is an unnecessary coupling between the components and can lead to passing props
back and forth between components.
获取数据时,您可能希望在页面或布局与其某些子组件之间共享获取结果。这是组件之间不必要的耦合,可能导致组件之间来回传递 props。
Instead, we recommend colocating data fetching alongside the component that consumes the data. fetch
requests are automatically deduped in Server Components, so each route segment can request exactly the data it needs without worrying about duplicate requests. Next.js will read the same value from the fetch
cache.
相反,我们建议将数据获取与使用数据的组件放在一起。 fetch 请求在 Server Components 中自动进行重复数据删除,因此每个路由段都可以准确地请求它需要的数据,而不必担心重复请求。 Next.js 将从获取缓存中读取相同的值。