React Server Components(RSC)是React架构中最具变革性的特性,将组件渲染边界从客户端扩展到服务端,实现了服务端渲染与客户端交互的无缝融合。在Web性能优化和前端工程化实践中,RSC通过减少客户端JavaScript体积、将数据获取移至服务端,有效解决了传统SSR方案中水合(hydration)开销大的问题。
React Server Components与Client Components的渲染边界
React Server Components是零客户端体积的组件——它们的代码永远不会被发送到浏览器,仅在服务端执行并生成序列化的React树。与之对应的Client Components则走传统的客户端渲染和水合流程。
两者的关键区别:
- Server Components:可直接访问数据库、文件系统和后端API,无状态、无副作用,不使用useState、useEffect等客户端Hook
- Client Components:使用
'use client'指令声明,支持状态管理、事件处理、浏览器API访问,代码打包到客户端bundle
Server Components可以导入Client Components,但Client Components不能直接导入Server Components——如果需要在Client Components中使用Server Components,必须通过children prop传递(即composition模式),避免服务端组件被打包到客户端。
Next.js App Router中RSC数据获取与流式渲染
Next.js 13+的App Router原生支持RSC,通过文件系统路由约定自动区分Server Components和Client Components:
// app/products/page.tsx - Server Component(默认)
import { db } from '@/lib/database'
import ProductCard from './ProductCard'
import { Suspense } from 'react'
// 直接在Server Component中执行数据库查询
async function getProducts() {
const products = await db.product.findMany({
take: 20,
orderBy: { createdAt: 'desc' }
})
return products
}
export default async function ProductsPage() {
return (
<div>
<h1>商品列表</h1>
{/* Suspense边界实现流式渲染,慢数据不阻塞页面首屏 */}
<Suspense fallback={<div>加载中...</div>}>
<ProductList />
</Suspense>
</div>
)
}
// 独立的异步Server Component,配合Suspense实现流式传输
async function ProductList() {
const products = await getProducts()
return (
<div className="grid">
{products.map(p => (
<ProductCard key={p.id} product={p} />
))}
</div>
)
}
// app/products/ProductCard.tsx - Client Component
'use client'
import { useState } from 'react'
export default function ProductCard({ product }: { product: Product }) {
const [isFavorite, setIsFavorite] = useState(false)
return (
<div className="card">
<h3>{product.name}</h3>
<p>¥{product.price}</p>
<button onClick={() => setIsFavorite(!isFavorite)}>
{isFavorite ? '已收藏' : '收藏'}
</button>
</div>
)
}
当页面请求到达时,Next.js会立即返回已准备好的HTML骨架(包含Suspense fallback),然后通过HTTP Streaming逐步推送ProductList渲染完成后的HTML片段。浏览器收到流式数据后会逐步替换fallback内容,用户无需等待所有数据加载完成即可看到页面。
RSC序列化协议与React Flight数据格式
React Server Components的渲染结果通过Flight协议序列化为特殊的文本格式传输。理解这个格式有助于排查RSC相关的渲染问题:
// React Flight序列化格式示例
M1:{"id":"./ProductCard.js","chunks":["client.js"],"name":""}
0:["$","div",null,{"className":"grid","children":[
["$","div",null,{"className":"card","children":[
["$","h3",null,{"children":"无线耳机"}],
["$","p",null,{"children":"¥299"}],
["$","$1",null,{"product":{"id":1,"name":"无线耳机","price":299}}]
]}]
]}]
其中M1标记是Client Component的模块引用,$1是对该模块的实例化引用。浏览器端的React运行时解析Flight数据后,会将Client Component的占位符替换为实际的客户端组件实例,并执行水合操作。
Server Actions表单处理与渐进增强
Server Actions是RSC生态中替代传统API路由的方案,允许在Server Components中直接定义可被Client Components调用的服务端函数:
// app/contact/page.tsx - Server Component with Server Actions
import { revalidatePath } from 'next/cache'
// 'use server'标记此函数为Server Action
async function submitContactForm(formData: FormData) {
'use server'
const name = formData.get('name') as string
const email = formData.get('email') as string
const message = formData.get('message') as string
// 直接写入数据库,无需定义API路由
await db.contactMessage.create({
data: { name, email, message }
})
// 触发路径重新验证,更新缓存
revalidatePath('/contact')
}
export default function ContactPage() {
return (
<form action={submitContactForm}>
<input type="text" name="name" placeholder="姓名" required />
<input type="email" name="email" placeholder="邮箱" required />
<textarea name="message" placeholder="留言内容" required />
<button type="submit">提交</button>
</form>
)
}
即使JavaScript未加载(渐进增强场景),表单依然可以通过原生HTML的form action提交并执行Server Action,保证核心功能在弱网环境下的可用性。
RSC与传统SSR的性能差异与迁移注意事项
RSC与传统SSR(如Next.js Pages Router的getServerSideProps)在架构上有本质区别:
- 传统SSR:整个页面在服务端渲染为HTML,所有组件代码都被发送到客户端执行水合,客户端bundle体积不减少
- RSC:Server Components代码不发送到客户端,客户端仅需加载Client Components的JavaScript,bundle体积可减少30%-50%
迁移到RSC架构时需注意:
- 第三方组件库如果依赖客户端生命周期(如window、document访问),需要用
'use client'包裹 - Context Provider需要放在Client Component中,因为Server Components无法使用React Context
- 状态共享场景需要通过URL参数、数据库或Server Actions传递,而非跨组件状态管理
RSC代表了React生态对服务端渲染的重新思考,通过组件级别的渲染边界划分,在开发体验和运行性能之间找到了新的平衡点。对于关注首屏加载速度和客户端bundle体积的项目,RSC架构提供了比传统SSR更优的解决方案。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/reactservercomponents-fu-wu-duan-zu-jian-xuan-ran-ji-zhi-yu/