主题
Next.js 的客户端组件和服务端组件讲解
更新: 9/26/2025字数: 0 字 时长: 0 分钟
在 Next.js 15 的 App Router 中,React 组件分为 Server Component(服务端组件) 和 Client Component(客户端组件);注意区分这两者的细节。
一、什么是 Server Component
默认组件类型 App Router 下,
app/目录里的组件默认都是 Server Component。运行环境 在 服务端 执行(Node.js),可直接访问数据库、文件系统、环境变量等。
特点
- 不会打包到浏览器,体积小。
- 不可使用 React Hook(如
useState,useEffect)。 - 可直接渲染 HTML,首屏渲染快,SEO 友好。
示例:
jsx
// app/page.js (Server Component)
export default function Page() {
return <h1>Hello from Server Component</h1>;
}二、什么是 Client Component
- 显式声明 在组件文件顶部添加:
jsx
"use client";运行环境 在 浏览器端 执行,可响应用户交互,使用 React Hook。
特点
- 可使用
useState,useEffect,useContext等 Hook。 - 体积较大,会被打包到客户端 JS。
- 适合处理按钮点击、表单、动画等动态交互。
- 可使用
示例:
jsx
"use client";
import { useState } from "react";
export default function Counter() {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(count + 1)}>Count: {count}</button>;
}三、Server Component 与 Client Component 的区别
| 特性 | Server Component | Client Component |
|---|---|---|
| 默认 | ✅ 默认 | ❌ 必须 "use client" |
| 执行位置 | 服务端(Node.js) | 浏览器 |
| 可访问数据库 / secrets | ✅ | ❌ 不安全 |
| React Hooks | ❌ | ✅ |
| 首屏渲染性能 | 高 | 较低(JS 加载) |
| 打包体积 | 小 | 大 |
| SEO | 优 | 差(需客户端渲染) |
四、嵌套规则
1. Server Component 可以嵌套 Client Component ✅
- 常见模式:页面或布局为 Server Component,局部组件为 Client Component。
jsx
// app/page.js
import Counter from "./Counter"; // Counter 是 Client Component
export default function Page() {
return (
<div>
<h1>Server Component</h1>
<Counter />
</div>
);
}注意
Server Component 嵌套 Client Component 时,必须通过 import 引入成组件。不能直接写在 Server Component 里。
Server/Client 嵌套示意
Page (Server)
├─ Header (Server)
├─ Counter (Client) ← 用 useState / useEffect
└─ Footer (Server)2. Client Component 不能嵌套 Server Component ❌
- 原因:浏览器无法执行 Server Component 的服务端逻辑。
- 如果尝试 import Server Component,会报错:
Error: Server component imported into a client component- 解决方法:将被嵌套组件改成 Client Component,或将 Server Component 提取到父组件。
五、为什么不能在 Server Component 里直接使用 Client Hook
- Server Component 运行在服务端,不存在浏览器环境。
- React Hook(
useState,useEffect)只能在客户端执行。 - 强制要求:要使用 Hook,必须在 Client Component 里。
- 错误示例:
jsx
export default function Page() {
const [count, setCount] = useState(0); // ❌ 报错
return <button onClick={() => setCount(count + 1)}>{count}</button>;
}六、最佳实践
尽量保持页面和布局为 Server Component
- 提升首屏渲染速度,减少 JS 包体积。
交互、状态管理、浏览器 API 组件用 Client Component
- 例如按钮计数器、表单、动态列表、动画。
嵌套规则
- Server Component → Client Component ✅
- Client Component → Server Component ❌
数据获取在 Server Component
- Server Component 可直接调用数据库 / fetch API,将数据传给 Client Component 只做渲染和交互。
布局优先 Server
- 页面整体布局尽量 Server Component,仅在局部需要交互的地方使用 Client Component。
- 页面和 Header、Footer 由服务端渲染。
- Counter 组件在浏览器端处理点击和状态。
- 保持 Server Component 不直接依赖 Client Hook。