Server Components 简介
本教程共 50 篇 · 第 47 篇 · 更新于 2026-07-29 · 约 10 分钟阅读
47. Server Components 简介
本节目标:理解 Server Components 是什么、和 SSR 有什么区别、什么时候该用哪一种。
RSC 解决什么问题
传统的 React 应用,所有组件都在浏览器里运行。
这意味着用户要下载所有组件的 JS,包括那些只负责”展示数据、不需要交互”的组件。
Server Components(RSC)是一种新组件类型:它在服务器上运行,只把渲染结果发给客户端。
传统模式
// 客户端组件:所有 JS 都要下载
function Article({ id }) {
const [article, setArticle] = useState(null);
useEffect(() => {
fetch(`/api/articles/${id}`).then(/* ... */);
}, [id]);
return (
<article>
<h1>{article.title}</h1>
<Author id={article.authorId} /> <!-- 又触发一次请求 -->
<p>{article.content}</p>
</article>
);
}
问题:JS 包大、请求瀑布(组件套组件地发请求)、重复的 JSON 序列化。
RSC 模式
// Server Component:在服务器上运行,直接读数据库
import db from './database';
async function Article({ id }) {
const article = await db.articles.get(id);
const author = await db.authors.get(article.authorId);
return (
<article>
<h1>{article.title}</h1>
<span>作者:{author.name}</span>
<p>{article.content}</p>
</article>
);
}
优势:零客户端 JS、直接访问数据源、没有请求瀑布。
三种组件类型
React 19 把组件分成三类:
| 类型 | 运行环境 | 能做什么 | 指令 |
|---|---|---|---|
| Server Component | 服务器 | 读文件、查数据库、渲染 UI | 默认(无指令) |
| Client Component | 浏览器 | useState、useEffect、事件处理 | "use client" |
| 共享组件 | 两者皆可 | 根据导入位置决定 | 无 |
Note没有指令的组件默认是 Server Component。这不是 Next.js 才有的,是 React 19 的标准。但需要注意:Server Components 需要框架支持(如 Next.js App Router、Remix 等)才能使用。纯客户端 React 项目(如仅用 Vite 搭建的项目)无法直接使用 Server Components。
两个指令
"use client" — 声明客户端组件
"use client";
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(count + 1)}>{count}</button>;
}
一个文件顶部加了 "use client",整个文件及其导入的所有组件都会变成客户端组件。
"use server" — 声明 Server Action
"use server";
import db from './database';
export async function createNote() {
await db.notes.create();
}
export async function deleteNote(id) {
await db.notes.delete(id);
}
"use server" 标记的函数在客户端调用时,React 会自动发请求到服务器执行。
Warning
"use server"不是声明 Server Component 的!Server Component 没有指令。"use server"用于 Server Actions。
组合模式
实际开发中,Server Component 和 Client Component 是嵌套使用的。
// 📄 ArticlePage.jsx(Server Component)
import db from './database';
import { LikeButton } from './LikeButton';
async function ArticlePage({ id }) {
const article = await db.articles.get(id);
return (
<article>
<h1>{article.title}</h1>
<p>{article.content}</p>
{/* 👇 客户端组件嵌套在服务端组件里 */}
<LikeButton articleId={id} initialLikes={article.likes} />
</article>
);
}
// 📄 LikeButton.jsx(Client Component)
"use client";
import { useState } from 'react';
export function LikeButton({ articleId, initialLikes }) {
const [likes, setLikes] = useState(initialLikes);
async function handleLike() {
const newLikes = await fetch(`/api/like`, {
method: 'POST',
body: JSON.stringify({ articleId })
});
setLikes(await newLikes.json());
}
return <button onClick={handleLike}>点赞 {likes}</button>;
}
规则:
- Server Component 可以导入 Client Component
- Client Component 不能导入 Server Component(因为服务器代码不能发到浏览器)
- Server Component 可以把 Server Component 作为 children 传给 Client Component
Server Actions
Server Actions 让客户端组件能调用服务器上的函数。
基本用法
在 Server Component 内定义:
// 📄 NoteList.jsx(Server Component)
import Button from './Button';
function NoteList() {
async function createNoteAction() {
"use server"; // 标记为 Server Action
await db.notes.create();
}
return <Button onClick={createNoteAction}>新建笔记</Button>;
}
作为独立模块:
// 📄 actions.js
"use server";
export async function createNote() {
await db.notes.create();
}
export async function deleteNote(id) {
await db.notes.delete(id);
}
// 📄 NoteList.jsx
"use client";
import { createNote, deleteNote } from './actions';
function NoteList() {
return (
<>
<button onClick={createNote}>新建</button>
<button onClick={() => deleteNote(1)}>删除</button>
</>
);
}
调用 createNote() 时,React 会在后台发请求到服务器。你不需要写 fetch。
表单直接绑定
Server Action 可以传给 <form action={...}>:
"use client";
import { updateName } from './actions';
function UpdateName() {
return (
<form action={updateName}>
<input type="text" name="name" />
<button type="submit">更新</button>
</form>
);
}
提交表单时 React 自动调 updateName(formData),不需要 onSubmit。
与 SSR 的区别
很多人搞混 RSC 和 SSR。它们是完全不同的东西:
| 维度 | SSR | RSC |
|---|---|---|
| 运行时机 | 请求时/构建时 | 构建时或请求时 |
| 输出 | HTML | 序列化组件树(RSC Payload) |
| JS Bundle | 包含所有组件 | 只包含客户端组件 |
| 交互 | 注水后全部可交互 | 服务端组件始终不可交互 |
| 重新获取 | 刷新整个页面 | 只重新请求变化的组件 |
SSR 和 RSC 可以组合使用:服务器组件渲染成 RSC Payload,再通过 SSR 转成 HTML。
什么时候用哪个
用 Server Component 的场景:
- 展示数据(读数据库、调 API)
- 渲染静态内容(markdown、文档)
- 不需要交互的 UI(列表、卡片、布局)
用 Client Component 的场景:
- 有交互(点击、输入、切换)
- 使用浏览器 API(localStorage、navigator)
- 使用 useState/useEffect
Tip经验法则:能用 Server Component 的就用,只在”必须交互”的地方加
"use client"。
限制
Server Component 的限制要记住:
- 不能用
useState、useEffect、useReducer等客户端 Hook - 不能用
onClick等事件处理 - 不能用浏览器专属 API
- 可以直接
await异步数据(async/await 组件) - 可以访问服务器资源(数据库、文件系统)
// ✅ 正确:Server Component 里直接 await
async function Page() {
const data = await db.query();
return <div>{data}</div>;
}
// ❌ 错误:Server Component 里用 useState
function Page() {
const [data, setData] = useState(null); // 报错!
// ...
}
小结
- Server Components 在服务器运行,不打包 JS 到客户端
- 默认无指令就是 Server Component
"use client"声明客户端组件"use server"声明 Server Action(不是声明 Server Component)- RSC 和 SSR 是独立的概念,可以组合
- 优先用 Server Component,只在需要交互时切到 Client Component