AI AgentTechnical Deep Dive

React Server Components 原理与应用 —— 前后端融合新范式

发布时间2026/03/29
分类AI Agent
预计阅读2 分钟
作者吴长龙
*

什么是 React Server Components?

01.内容

什么是 React Server Components?

React Server Components(RSC)是 React 18 引入的重大特性,它允许组件在服务端运行,只将渲染结果发送到客户端。

核心概念

#### 服务端组件 vs 客户端组件

jsx snippetjsx
// Server Component(默认)- 在服务端运行
async function ServerComponent() {
  const data = await db.query('SELECT * FROM posts');
  // 可以直接访问数据库、文件系统
  return (
    <ul>
      {data.map(post => (
        <li key={post.id}>{post.title}</li>
      ))}
    </ul>
  );
}

// 客户端组件 - 在浏览器运行
'use client';
function ClientComponent() {
  const [count, setCount] = useState(0);
  return <button onClick={() => setCount(c => c + 1)}>{count}</button>;
}

#### 关键特性

特性服务端组件客户端组件
运行位置服务端浏览器/客户端
直接访问数据库
使用 useState/Effect
交互事件
打包到 bundle
可以是 async

工作原理

#### 1. 流式 SSR + 选择性水合

传统 SSR:整页渲染完成后才开始 hydration

RSC 方式:

code snippetcode
服务端:组件树 → 序列化 → 流式输出
         ↓
客户端:逐步接收 → 选择性 hydration

#### 2. Server Action

服务端组件可以定义"服务端 action",客户端调用:

jsx snippetjsx
// Server Component
async function AddPost() {
  async function createPost(formData) {
    'use server'; // 标记为服务端执行
    await db.posts.create({
      title: formData.get('title')
    });
    revalidatePath('/posts');
  }
  
  return (
    <form action={createPost}>
      <input name="title" />
      <button type="submit">提交</button>
    </form>
  );
}

#### 3. 数据获取模式

jsx snippetjsx
// 服务端组件中直接获取数据
async function PostList() {
  const posts = await fetchPosts(); // 服务端执行,无额外 API
  
  return (
    <ul>
      {posts.map(post => (
        <PostItem key={post.id} post={post} />
      ))}
    </ul>
  );
}

// 客户端组件通过 server action 或 props 接收数据
'use client';
function PostItem({ post }) {
  return <li>{post.title}</li>;
}

实际应用场景

#### 1. 数据密集型页面

jsx snippetjsx
// 不需要 API 层,直接在服务端获取
async function Dashboard() {
  const users = await db.users.count();
  const orders = await db.orders.count();
  const revenue = await db.orders.sum('amount');
  
  return (
    <div>
      <Stat name="用户" value={users} />
      <Stat name="订单" value={orders} />
      <Stat name="收入" value={revenue} />
    </div>
  );
}

#### 2. 保护敏感逻辑

jsx snippetjsx
// 服务端组件访问环境变量,不会泄露到客户端
async function APIKeyDisplay() {
  const apiKey = process.env.SECRET_KEY; // 仅服务端可见
  // 处理逻辑...
  return null;
}

#### 3. 大型列表优化

jsx snippetjsx
// 服务端渲染列表,客户端只 hydration 交互部分
async function ArticleList() {
  const articles = await db.articles.findMany();
  
  return (
    <div>
      {articles.map(article => (
        <ArticleCard 
          key={article.id} 
          article={article}
          // 客户端组件处理交互
          actions={<ArticleActions id={article.id} />}
        />
      ))}
    </div>
  );
}

Next.js App Router 中的 RSC

Next.js 13+ 默认使用 App Router,组件默认是服务端组件:

jsx snippetjsx
// app/posts/page.tsx
export default async function PostsPage() {
  const posts = await getPosts();
  
  return (
    <main>
      {posts.map(post => (
        <PostCard key={post.id} post={post} />
      ))}
      <NewPostForm /> {/* 客户端组件 */}
    </main>
  );
}

// app/posts/NewPostForm.tsx
'use client';
export function NewPostForm() {
  // 交互逻辑...
}

常见陷阱

#### 1. 混淆服务端/客户端组件

jsx snippetjsx
// 错误:服务端组件不能使用 useState
async function BadComponent() {
  const [count, setCount] = useState(0); // ❌
  return <div>{count}</div>;
}

// 正确:客户端组件需要 'use client'
'use client';
function GoodComponent() {
  const [count, setCount] = useState(0);
  return <div>{count}</div>;
}

#### 2. 服务端组件中使用 window/document

jsx snippetjsx
// 错误:服务端没有 window
async function BadComponent() {
  const width = window.innerWidth; // ❌
  return <div>{width}</div>;
}

#### 3. 过度使用服务端组件

jsx snippetjsx
// 如果需要大量交互,还是用客户端组件
'use client';
function InteractiveChart() {
  // 图表交互逻辑...
}

性能影响

指标传统 SSRRSC
首屏时间依赖 JS 加载更快(流式)
Bundle 大小全量 JS仅客户端 JS
水合成本全量 hydration选择性 hydration
数据获取客户端请求服务端直连

总结

RSC 代表了 React 的未来方向:

  • 更少的 JavaScript:只发送必要的客户端代码
  • 更好的首屏性能:流式渲染 + 选择性 hydration
  • 更简单的数据获取:直接访问后端资源
  • 更清晰的架构:服务端/客户端职责分离

掌握 RSC,是 React 开发者必须面对的进阶之路。