React Server Components 把渲染从浏览器前移到服务器,JS 体积与数据请求双降。本文讲清服务组件与客户端组件的边界划分原则、落地四步法、序列化与数据获取的四个高频坑,以及老项目并存迁移的实操策略。
2026 年,React Server Components(RSC)已经从「实验特性」变成主流生产架构:React 19(当前 19.2.8)把 RSC 协议纳入稳定面,Next.js App Router、RedwoodJS 等框架都默认以 RSC 为骨架。但很多团队是「先用了再说」,对它的运行模型理解模糊,导致客户端包没有真正变小、数据请求也没有真正变少。这篇把 RSC 的核心模型、落地步骤和常见坑一次讲清。
一、RSC 改变了什么:渲染位置从「浏览器」前移到「服务器」
传统 SPA 是「一个 HTML 壳 + 一大坨 JS」,所有渲染、数据获取都在浏览器完成。RSC 把组件分成两类:
- 服务组件:只在服务器执行,可以直接
await数据库/文件/内部服务,产物是序列化后的 RSC Payload,不进客户端 bundle; - 客户端组件:文件顶部标
"use client",和传统组件一样水合运行,负责交互与状态。
收益是两端的:客户端 JS 显著变小(服务组件零字节下发),数据获取在服务器内网完成,省掉了浏览器到 API 的多次往返。官方立场参考 React 官方博客。

二、落地四步:从混用到分清边界
大多数团队的正确路径是「默认服务组件,按需下沉客户端」,而不是反过来:
- 默认全是服务组件:新页面不写
"use client",数据获取、模板、SEO 相关内容都放服务端; - 只在叶子节点加
"use client":输入框、轮播、弹窗这类真正需要交互的组件; - 把 children 穿过边界:客户端组件通过
children接收服务组件渲染结果,避免把整个子树拖进客户端; - 校验收益:用 bundle 分析确认 JS 体积与请求瀑布确实下降,否则说明边界划错了。
// app/product/page.tsx —— 服务组件:直接取数,零客户端 JS
import { AddToCart } from "./add-to-cart"; // 客户端组件
export default async function Page({ params }) {
const product = await db.product.find(params.id); // 服务器内网直连
return (
<section>
<ProductDetail product={product} />
{/* 只有按钮是客户端的,整个详情树不进 bundle */}
<AddToCart id={product.id} />
</section>
);
}
三、最容易踩的四个坑
四、迁移期策略:并存,不搞一刀切
RSC 与传统组件可以在同一应用共存,框架按文件粒度识别。建议迁移期保留原页面路由不动,新页面全部走 RSC;对老页面按流量从低到高逐个改造,每改造一个页面用真实用户数据对比 LCP/INP 与 JS 传输体积。Next.js 文档对 App Router 下的缓存与流式语义有完整说明,迁移前值得通读一遍,很多「性能没变好」的问题出在对缓存默认值的误解上。
一句话总结:RSC 的本质是把「组件树」变成「客户端与服务端协作的协议」,边界划得越精细,两端各干擅长的事,收益越大。
#React#Server Components#前端架构#React 19

