【Next】客户端组件和服务端组件

概述

在 Next.js(尤其是 App Router 体系)里,客户端组件(Client Component)和服务端组件(Server Component) 是基于 React 的 RSC(React Server Components)模型实现的。

  • 服务端组件(Server Component)默认执行在服务端(Node.js),用于数据获取、减少 bundle
  • 客户端组件(Client Component)运行在浏览器,用于交互、状态、事件
  • 二者通过 序列化协议(Flight) 进行通信
能力 Server Client
访问数据库 ✅ ❌
使用 useState ❌ ✅
使用 useEffect ❌ ✅
绑定事件 onClick ❌ ✅
减少 bundle 体积 ✅ ❌
tsx 复制代码
// 默认就是 Server Component
export default function Page() {
  return <div>Hello</div>;
}
tsx 复制代码
// 显式声明 Client Component
"use client";

export default function Button() {
  return <button onClick={() => alert(1)}>Click</button>;
}

"use client" 是一个 编译时指令(不是运行时)

Server Component 深入

为什么默认是 Server?

核心目标:减少前端 bundle + 提升首屏性能

tsx 复制代码
// 直接在服务端查数据
async function Page() {
  const data = await fetch("https://api.com/user");
  return <div>{data.name}</div>;
}
  • ❌ 不需要把 fetch 逻辑打包到浏览器
  • ❌ 不需要 useEffect + loading
  • ✅ SSR 天然支持

可以直接访问后端资源

ts 复制代码
import db from "@/lib/db";

export default async function Page() {
  const users = await db.user.findMany();
  return <div>{users.length}</div>;
}
  • Prisma
  • 内部 RPC(BFF)
  • GraphQL

不支持交互

tsx 复制代码
// ❌ 错误
export default function Page() {
  return <button onClick={() => {}}>Click</button>;
}
  • Server Component 不会在浏览器执行
  • 没有事件系统

Client Component 深入

只要涉及以下任意一点,就需要使用客户端组件:

  • useState
  • useEffect
  • DOM 操作
  • 事件(onClick)
  • 浏览器 API(localStorage)
tsx 复制代码
"use client";

import { useState } from "react";

export default function Counter() {
  const [count, setCount] = useState(0);

  return (
    <button onClick={() => setCount(count + 1)}>
      {count}
    </button>
  );
}
  • 会被打进 JS bundle
  • 会增加 hydration 成本
  • 会影响 TTI

所以 能不用 client 就不用

核心机制

Server → Client 的传输原理(Flight)

Server Component 渲染后不会直接输出 HTML,而是:

输出一种特殊 JSON(React Flight)

示意:

json 复制代码
[
  ["div", null, "Hello"],
  ["$L1", "Button"]
]

客户端再:

  • 解析结构
  • 加载对应 Client Component
  • Hydration

限制:只能传"可序列化数据"

tsx 复制代码
// ❌ 错误
<ClientComp fn={() => {}} />
tsx 复制代码
// ✅ 正确
<ClientComp count={1} />

因为需要跨网络传输

组合模式

推荐结构:Server + Client 嵌套

tsx 复制代码
// Server Component
import Button from "./Button";

export default async function Page() {
  const data = await fetchData();

  return (
    <div>
      <h1>{data.title}</h1>
      <Button />
    </div>
  );
}
tsx 复制代码
// Client Component
"use client";

export default function Button() {
  return <button>Click</button>;
}

注意: Client 不能 import Server

tsx 复制代码
// ❌ 错误
"use client";
import ServerComp from "./ServerComp";
tsx 复制代码
// ✅ Server 可以 import Client
相关推荐
Devlive 开源社区9 小时前
AuthX 正式更名 GrantForge:我们重新做了一遍权限管理系统
大数据·人工智能·架构
To_OC9 小时前
从一头雾水到跑通全流程:我用一个周末啃透了JWT登录鉴权
前端·后端·http
微三云生态系统架构师-彭丹10 小时前
抖店OPC智能选品与铺货架构:多店差异化与频率风控设计
架构
集智飞行11 小时前
无人机集群通信架构剖析,以及对未来发展的几点判断
架构·无人机
想要打 Acm 的小周同学呀11 小时前
无需自己设计Agent架构的业务系统,依赖第三方Agent,基于SKILL和MCP服务实现企业级内部提效工具开发
架构·agent
excel11 小时前
研究 Vue 3 源码的收获
前端·vue.js
Dawson Zhu13 小时前
《Agentic Design Patterns》第 4 章导读:反思(Reflection)
人工智能·语言模型·架构·aigc·agi
可乐鸡翅yeah_13 小时前
业务中 M3U8 水印相关坑,硬水印和动态水印区别
前端·网络·数据库·ffmpeg·m3u8在线
lerhxx13 小时前
AI 应用如何高效优雅地恢复中断?—— "连接解耦 + 状态持久化"
前端·javascript
计算机魔术师13 小时前
METR 演示 AI 智能体如何篡改 Inspect 评估记录以掩盖不当行为
前端