← 返回题目列表

React Server Components 和传统 SSR 有什么区别?

高频 困难 第 14 / 25 题 更新于 2026/07/29
React Server ComponentsSSRNext.js同构

简化版

传统 SSR 是服务端把组件渲染成 HTML,再由客户端 hydrate 变得可交互;React Server Components 是让部分组件只在服务端运行,输出可被客户端合并的组件载荷,不把这些组件代码打进客户端包。RSC 主要解决数据获取靠近服务端、减少客户端 JS 和保护服务端能力的问题,不等同于 SSR。

详细版

传统 SSR 的核心产物是 HTML,客户端仍需要下载对应组件 JS 做 hydration。RSC 的核心产物是服务端组件树描述,Server Component 可以直接访问数据库、文件系统或服务端 API,但不能使用浏览器事件和客户端状态;需要交互时要切到 Client Component。

Server Component: 取数据、拼结构、减少客户端 JS
Client Component: useState、useEffect、onClick、浏览器 API

在 Next.js App Router 中,组件默认是 Server Component,写 'use client' 才进入客户端边界。面试要强调:RSC 可以和 SSR、SSG、Streaming 一起使用,它是组件执行位置的模型,不是单独的渲染模式。

完整版教学

一、先分清两个问题

SSR 回答的是“HTML 在哪里生成”,RSC 回答的是“组件代码在哪里执行”。这两个问题经常一起出现,但不是同一个维度。

问题SSRRSC
关注点首屏 HTML 生成组件执行环境
主要产物HTML服务端组件载荷
客户端 JS通常仍要 hydrateServer Component 不进客户端包
数据获取页面级或服务端阶段组件级靠近数据源

记忆钩子:SSR 管“先吐 HTML”,RSC 管“哪些组件不用下发 JS”。

二、传统 SSR 的工作流

浏览器请求 /product/1
  -> Node 服务端执行 React 渲染
  -> 返回 HTML
  -> 浏览器下载 JS
  -> hydrate 绑定事件

SSR 的优势是首屏有 HTML,SEO 和首屏感知更好。代价是服务端每次请求要渲染,客户端仍要下载组件 JS 并 hydration。如果页面有 200KB 交互组件,SSR 只解决 HTML 首屏,不自动消除这 200KB JS。

三、RSC 的工作流

Server Component 执行在服务端
  -> 读取数据
  -> 生成组件树描述
  -> Client Component 边界下载 JS 并交互

Server Component 可以写成异步组件,直接在服务端取数据:

async function ProductPage({ id }) {
  const product = await db.product.findUnique({ where: { id } })
  return <ProductView product={product} />
}

这段代码不会作为浏览器 JS 下发,因此数据库访问逻辑和依赖不会进入客户端包。真正需要点击、状态、浏览器 API 的部分再放到 Client Component。

四、Server 和 Client 边界

'use client'

export function AddToCartButton({ id }) {
  const [loading, setLoading] = useState(false)
  return <button onClick={() => setLoading(true)}>加入购物车</button>
}

'use client' 标记的是模块边界。被它标记的组件及其客户端依赖会进入客户端 bundle,可以使用 useStateuseEffect、事件处理和浏览器 API。

Server Component 可以引用 Client Component,但 Client Component 不能直接导入 Server Component。否则客户端包会试图包含服务端能力,边界就乱了。

五、RSC 带来的收益

收益原因
减少客户端 JS服务端组件代码不下发
数据获取靠近数据源服务端组件可直接访问服务端资源
安全边界更清晰密钥和数据库逻辑留在服务端
组合更细组件级拆分服务端和客户端职责

假设一个 Markdown 渲染库 80KB,只用于把文章内容渲成静态结构。放在 Client Component 会增加客户端 JS;放在 Server Component 中,用户只拿到渲染结果,不需要下载这 80KB 渲染库。

六、RSC 的限制和心智成本

Server Component 不能使用浏览器 API,不能绑定事件,也不能使用客户端状态 Hook。它还要求数据必须可序列化地传给 Client Component,函数、数据库连接、类实例等不能随便跨边界传递。

Server -> Client props:
  可以: string、number、plain object、array
  谨慎: Date、Map、class instance
  不行: function、DB connection

这带来新的架构心智:组件不再只是 UI 单元,也带有运行环境属性。团队需要约定哪些组件放服务端,哪些组件放客户端。

七、常见误区与追问

  • 误区:RSC 就是 SSR 的新名字。 SSR 是渲染 HTML 的方式,RSC 是组件执行环境模型。
  • 误区:Server Component 可以写 onClick。 事件处理需要 Client Component。
  • 误区:用了 RSC 就没有 hydration。 Client Component 边界仍需要下载 JS 并 hydrate。
  • 追问:RSC 为什么能减少 JS? Server Component 代码和服务端依赖不进入客户端 bundle。
  • 追问:'use client' 标记什么? 标记模块进入客户端组件边界,而不是只标记某一行逻辑。
  • 追问:RSC 能访问数据库吗? 可以在服务端环境访问,但不要把敏感结果无控制传给客户端。

八、加强记忆

RSC 和 SSR 要用两个维度记:SSR 是“服务端先生成 HTML”,RSC 是“组件可选择只在服务端执行”。Server Component 负责取数据、拼静态结构、减少客户端 JS;Client Component 负责状态、事件和浏览器能力。两者可以组合,不能混为一个概念。