React Server Components(RSC)是 React 18 引入的渲染架构范式,将组件拆分为 Server Components 和 Client Components 两种类型,实现服务端渲染与客户端交互的精细控制。RSC 不是 SSR 的替代,而是将组件级别的渲染职责重新分配,减少客户端 JavaScript 体积,提升首屏加载性能。
React Server Components架构原理与渲染模型
传统 React SSR 的流程是:服务端将整个组件树渲染为 HTML 字符串返回,客户端 hydrate 后接管全部组件的交互。所有组件的 JavaScript 代码都会被打包发送到浏览器,即使部分组件是纯展示型的,不依赖客户端交互。
RSC 引入了组件级别的渲染位置区分:
– Server Components:在服务端渲染,输出序列化的 RSC Payload,代码不发送到浏览器。可以直接访问数据库、文件系统、环境变量等后端资源
– Client Components:在客户端渲染,拥有完整的 React 交互能力(useState、useEffect、事件处理)。通过 “use client” 指令声明
– Shared Components:既可以在服务端也可以在客户端使用的组件,不含服务端专属 API 也不含客户端专属 Hook
RSC Payload 是一种类似 JSON 的流式序列化格式,服务端将渲染结果以该格式发送给客户端,客户端 React 运行时解析 Payload 并构建虚拟 DOM。由于 Server Components 的代码不包含在客户端 bundle 中,大型组件库不会增加前端包体积。
Server Components与Client Components边界划分
“use client” 指令定义了 Client Components 的边界。该指令标记模块文件级别,而非组件级别。被标记为 client 的文件中所有导出的组件都是 Client Components。
// app/components/Counter.tsx
"use client";
import { useState } from 'react';
export function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<button onClick={() => setCount(c => c + 1)}>Count: {count}</button>
</div>
);
}
Server Component 直接使用 async/await 获取数据,无需 useEffect 或 SWR:
// app/components/UserList.tsx
import { db } from '@/lib/db';
import { Counter } from './Counter';
export async function UserList() {
const users = await db.user.findMany({
take: 20,
orderBy: { createdAt: 'desc' }
});
return (
<section>
<h2>用户列表</h2>
<ul>
{users.map(u => (
<li key={u.id}>{u.name}</li>
))}
</ul>
<Counter /> {/* Client Component 嵌入 */}
</section>
);
}
关键原则:Server Component 可以导入 Client Component,但 Client Component 不能直接导入 Server Component。Client Component 需要使用 Server Component 时,通过 children prop 传递:
// ClientLayout.tsx
"use client";
export function ClientLayout({ children }: { children: React.ReactNode }) {
return <div className="interactive-wrapper">{children}</div>;
}
// page.tsx (Server Component)
<ClientLayout>
<ServerComponent /> {/* 通过 children 传递,合法 */}
</ClientLayout>
RSC数据获取模式与流式渲染优化
Server Components 通过 async 组件直接 await 数据,消除了客户端瀑布式请求问题。结合 Suspense 实现流式渲染:
// app/page.tsx
import { Suspense } from 'react';
import { UserList } from './UserList';
import { Dashboard } from './Dashboard';
export default function Page() {
return (
<main>
<h1>管理后台</h1>
<Suspense fallback={<p>加载用户数据...</p>}>
<UserList />
</Suspense>
<Suspense fallback={<p>加载仪表盘...</p>}>
<Dashboard />
</Suspense>
</main>
);
}
Suspense 边界使页面不再被最慢的组件阻塞。服务端在 UserList 数据未就绪时先返回 fallback 内容,数据就绪后以 RSC 流式格式增量推送,客户端 React 自动替换 fallback HTML。
Server Actions表单处理与数据变更
Server Actions 允许在 Client Component 中直接调用服务端函数,无需手动编写 API 路由:
// app/actions/user.ts
"use server";
import { revalidatePath } from 'next/cache';
import { db } from '@/lib/db';
export async function createUser(formData: FormData) {
const name = formData.get('name') as string;
const email = formData.get('email') as string;
await db.user.create({ data: { name, email } });
revalidatePath('/users'); // 触发缓存重新验证
}
// app/users/new/page.tsx
import { createUser } from '@/app/actions/user';
export default function NewUserPage() {
return (
<form action={createUser}>
<input name="name" type="text" placeholder="姓名" required />
<input name="email" type="email" placeholder="邮箱" required />
<button type="submit">创建</button>
</form>
);
}
Server Actions 自动处理 CSRF 防护,表单提交在不支持 JavaScript 的浏览器中也能工作(渐进增强)。
RSC缓存策略与按需重新验证机制
Next.js App Router 提供了多层级缓存机制:
– Request Memoization:同一请求内相同 fetch 调用自动去重
– Data Cache:跨请求缓存的 fetch 结果,通过 revalidate 或 tags 控制失效
– Full Route Cache:整个路由的 RSC Payload 缓存在服务端
– Router Cache:客户端缓存已访问路由的 RSC Payload,实现前进/后退即时导航
按需重新验证:
import { revalidateTag, revalidatePath } from 'next/cache';
// 按 tag 重新验证
fetch('https://api.example.com/users', {
next: { tags: ['users'] }
});
// 在 Server Action 或 API Route 中触发
export async function updateUser(formData: FormData) {
// ... 数据库操作
revalidateTag('users'); // 所有标记为 users 的缓存失效
revalidatePath('/users/[id]', 'page'); // 特定路由缓存失效
}
这种缓存架构使 Server Components 在数据获取阶段直接命中服务端缓存,避免重复查询数据库。ISR(Incremental Static Regeneration)在 RSC 中通过 revalidate 参数实现:fetch(url, { next: { revalidate: 3600 } }) 表示数据缓存 1 小时,过期后下一次请求触发后台重新生成。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/reactservercomponents-fu-wu-duan-zu-jian-jia-gou-yu-shu-ju/