Skip to content
 

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 ComponentClient 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>;
}

六、最佳实践

  1. 尽量保持页面和布局为 Server Component

    • 提升首屏渲染速度,减少 JS 包体积。
  2. 交互、状态管理、浏览器 API 组件用 Client Component

    • 例如按钮计数器、表单、动态列表、动画。
  3. 嵌套规则

    • Server Component → Client Component ✅
    • Client Component → Server Component ❌
  4. 数据获取在 Server Component

    • Server Component 可直接调用数据库 / fetch API,将数据传给 Client Component 只做渲染和交互。
  5. 布局优先 Server

    • 页面整体布局尽量 Server Component,仅在局部需要交互的地方使用 Client Component。
  • 页面和 Header、Footer 由服务端渲染。
  • Counter 组件在浏览器端处理点击和状态。
  • 保持 Server Component 不直接依赖 Client Hook。

我见青山多妩媚,料青山见我应如是。