主题
06 · Server Components vs Client Components
目标:默认按 Server Component 思考;只在交互边界加
'use client';能说清不能混用的点。
官方主文:Server and Client Components · Server Components (react.dev) · Directives
1. 一句话心智
| 类型 | 在哪跑 | 典型能力 | 典型不能 |
|---|---|---|---|
| Server Component(默认) | 服务器 | 直接读 DB/文件、async 组件、保密逻辑 | useState / 浏览器事件 / 大部分 hooks |
| Client Component | 服务器预渲染 + 浏览器水合 | state、effects、事件、浏览器 API | 把密钥写进包;别默认整树 Client |
Next App Router 里:没写 'use client' 的 app/** 组件默认是 Server。'use client' 标的是模块边界:该文件及其导入的子模块进入客户端包(仍可接收 Server 传来的 children)。
2. 决策表(日常够用)
| 需求 | 选 |
|---|---|
| 展示服务端读到的列表 | Server |
| 按钮、输入、本地过滤 | Client(尽量小叶子) |
useEffect / useState | Client |
读 process.env 密钥、读本地文件 | Server(或 Server Action) |
| 第三方「必须在浏览器」的图表库 | Client 包装一层 |
反模式:根 layout.tsx 顶部就 'use client' → 整站变 SPA 心智,RSC 白学。
3. 组合模式:Server 壳 + Client 叶子
app/sc-lab/page.tsx(Server,可 async):
tsx
import { Counter } from './counter'
async function getMotto() {
// 演示:假装服务端数据
return 'Server 渲染的一句座右铭'
}
export default async function ScLabPage() {
const motto = await getMotto()
return (
<main style={{ padding: 24 }}>
<h1>RSC Lab</h1>
<p>{motto}</p>
<Counter label="客户端计数" />
</main>
)
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
app/sc-lab/counter.tsx(Client 叶子):
tsx
'use client'
import { useState } from 'react'
export function Counter({ label }: { label: string }) {
const [n, setN] = useState(0)
return (
<div>
<p>
{label}: {n}
</p>
<button type="button" onClick={() => setN((x) => x + 1)}>
+1
</button>
</div>
)
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
访问 /sc-lab:座右铭来自 Server;按钮只在 Client。
4. 不能做的事(考试常考点)
| 错误 | 原因 |
|---|---|
在 Server 文件里 useState | 无客户端 hooks |
| 把函数 props(事件)从 Server 传给 Client 当回调 | 不可序列化;应把交互放进 Client,或用 Server Actions(08) |
Client 组件里直接 fs.readFile | 浏览器无 Node fs;放到 Server / Action |
| 从 Client 导入 Server-only 模块 | 打包边界炸;用官方 server-only 包可防误用 |
传递规则口诀:Server → Client 可以传可序列化数据(props)与 children;反过来不要指望「Client 随便调 Server 函数」——写操作用 Actions。
5. Vue / Journal 对照
| 你熟悉的 | 这里 |
|---|---|
| 整页都是浏览器 Vue | Next 默认先在服务器出 HTML/RSC 载荷 |
| Pinia 全局状态 | 先问:能否放 URL / Server 数据?再 Client |
Koa 里读库再 res.json | Server Component 里直接取数再渲染(07) |
6. 必做验收
- [ ] 读完 Next「Server and Client Components」入门页
- [ ]
/sc-lab跑通:Server 文案 + Client 计数 - [ ] 能指出项目里哪些文件有
'use client'、为什么 - [ ] 故意在 Server
page.tsx写useState,看报错,再改回
7. AI 提示词约束(本篇)
text
技术约束:Next.js App Router。
请把交互限制在尽可能小的 Client 叶子组件;
默认页面保持 Server Component。
审查时列出:每个 'use client' 的必要性;
不可序列化 props;是否误用 Pages Router API。
引用 nextjs.org 与 react.dev/reference/rsc 相关页。1
2
3
4
5
6
2
3
4
5
6
