React 服务器组件
React 服务器组件是一种新型的组件,它在打包之前,在独立于客户端应用程序或 SSR 服务器的环境中提前渲染。Rspack v2.0.0 及更高版本已内置对服务器组件的完整支持。
如何使用
Rspack 提供两种方案来支持 React 服务器组件:
- 使用 Rsbuild:Rsbuild 提供对 React 服务器组件开箱即用的支持,能够快速创建一个 React 服务器组件项目,详见 rsbuild-plugin-rsc。
- 手动配置 Rspack:你可以参考当前文档,手动添加 React 服务器组件相关的配置。
示例
rspack-rsc-examples 仓库包含了使用 Rspack 构建 React 服务器组件应用的完整示例。
安装依赖
npm install react react-dom react-server-dom-rspack
yarn add react react-dom react-server-dom-rspack
pnpm add react react-dom react-server-dom-rspack
bun add react react-dom react-server-dom-rspack
deno add npm:react npm:react-dom npm:react-server-dom-rspack
Tip
React 服务器组件依赖于 React 19 的新架构。请确保 react 和 react-dom 的版本均为 v19.1.0 或更高。
基本概念
React 服务器组件产物需要在服务器和浏览器两种环境中协同运行。为了支持这种架构,Rspack 启动 两个 Compiler 实例 分别构建服务端和浏览器端的产物,下图展示了整体的构建流程:

- Client Compiler (
target: 'web'): 负责生成运行在浏览器的代码。它主要打包客户端组件,以及应用所需的 CSS 和静态资源,处理组件的水合(Hydration)逻辑。
- Server Compiler (
target: 'node'): 负责生成运行在服务器的代码。它负责预渲染 React 服务器组件,并打包 Server Actions 的执行逻辑,同时处理服务端渲染(SSR)相关的代码。
在配置文件中,对应于两个 Compiler 配置:
rspack.config.mjs
export default [
// Client Compiler:构建浏览器端资源
{
target: 'web',
// ...客户端特定配置
},
// Server Compiler:构建 RSC Payload 和 Server Actions
{
target: 'node',
// ...服务端特定配置
},
];
配置插件
Rspack 通过一对协同工作的插件来支持 React 服务器组件。你需要调用一次 rsc.createPlugins() 得到 ServerPlugin 和 ClientPlugin,并分别挂到对应的 Compiler 上:
rspack.config.mjs
import { experiments } from '@rspack/core';
const { createPlugins, Layers } = experiments.rsc;
const { ServerPlugin, ClientPlugin } = createPlugins();
export default [
{
// Client Compiler
target: 'web',
plugins: [new ClientPlugin()],
// ...客户端特定配置
},
{
// Server Compiler
target: 'node',
plugins: [new ServerPlugin()],
// ...服务端特定配置
},
];
这两个插件会在内部调度 Client Compiler 和 Server Compiler 的构建流程,同步编译状态、模块信息,生成客户端引用清单等。
配置构建入口
你需要分别为 Client Compiler 和 Server Compiler 配置入口。Client Compiler 中 必须 存在与 Server Compiler 同名的入口。
rspack.config.mjs
export default [
{
target: 'web',
entry: {
// 必须存在与服务端同名的 'main' 入口,作为客户端 RSC 运行时的模块图根节点
main: { import: './src/entry.client.tsx' },
},
},
{
target: 'node',
entry: {
// 服务端入口名称为 'main'
main: { import: './src/entry.rsc.tsx' },
},
},
];
当 Server Compiler 在服务端代码中扫描到 "use client" 组件时,会把这些模块交给 Client Compiler 构建。由于 Client 侧可以配置多个入口,RSC 插件约定:与 Server 入口同名的 Client 入口即视为该 RSC 运行时的挂载点。
扫描到的 "use client" 模块会被注入到该同名入口的模块图中。若未配置同名入口,插件会报错「RSC Client Entry Mismatch」,客户端组件将无法在浏览器端正确加载。
配置 layer
在 Server Compiler 中,Rspack 使用 layer 区分 RSC 与 SSR 环境。RSC 插件使用的层名为:
Layers.rsc('react-server-components'):RSC 环境。只有在此层下的模块,Loader 才会把 "use client" 转成客户端引用、把 "use server" 注册为 Server Action。
Layers.ssr('server-side-rendering'):SSR 环境。用于标识 SSR 入口;若无模块被分配到此层,Rspack 会跳过 SSR 产物生成。
rspack.config.mjs
import path from 'node:path';
const ssrEntry = path.resolve(
import.meta.dirname,
'src/framework/entry.ssr.tsx',
);
const rscEntry = path.resolve(
import.meta.dirname,
'src/framework/entry.rsc.tsx',
);
export default [
// ...
{
target: 'node',
module: {
rules: [
// 将 SSR 入口分配给 Layers.ssr
{
resource: ssrEntry,
layer: Layers.ssr,
},
// 为 rsc layer 下的入口配置 resolve.conditionNames
{
resource: rscEntry,
layer: Layers.rsc,
resolve: {
conditionNames: ['react-server', '...'],
},
},
{
issuerLayer: Layers.rsc,
exclude: ssrEntry,
resolve: {
conditionNames: ['react-server', '...'],
},
},
],
},
// ...
},
];
页面或路由入口
"use server-entry" 是 Rspack 引入的一个特有指令,主要面向框架开发者,用于将服务器组件标记为页面或路由的逻辑入口。
Rspack 编译 "use server-entry" 组件时,会生成浏览器初始化 RSC 应用所需的完整资源,并直接在导出的组件上挂载静态属性来记录这些信息:
- entryJsFiles:启动脚本。对应 Client Compiler 中同名构建入口的产物,负责在浏览器端初始化 React 运行时和渲染流程。
- entryCssFiles:样式资源。Rspack 会收集该服务器组件及其子服务器组件树中依赖的所有 CSS 文件。

Todos.tsx
'use server-entry';
import './Todos.css';
import { Dialog } from './Dialog';
import { TodoDetail } from './TodoDetail';
import { TodoCreate } from './TodoCreate';
import { TodoList } from './TodoList';
export async function Todos({ id }: { id?: number }) {
// ...组件逻辑
}
在服务端运行时,你可以直接访问这些挂载在组件上的静态属性,来构建 HTML 头部资源:
entry.rsc.tsx
import type { ServerEntry } from 'react-server-dom-rspack/server.node';
const { Todos } = await import('../Todos.tsx');
const serverEntry = Todos as ServerEntry<typeof Todos>;
const root = (
<>
{/* 读取组件上的静态属性,注入当前路由的 CSS */}
{serverEntry.entryCssFiles
? serverEntry.entryCssFiles.map((href) => (
<link
key={href}
rel="stylesheet"
href={href}
precedence="default"
></link>
))
: null}
<Todos id={id} />
</>
);
const response = await handleRequest({
request,
getRoot: () => root,
bootstrapScripts: serverEntry.entryJsFiles, // 读取组件上的静态属性,作为启动脚本
nonce,
});
配置 JSX/TSX
添加 builtin:swc-loader 处理 .jsx / .tsx,并开启 rspackExperiments.reactServerComponents,以启用对 "use client"、"use server"、"use server-entry" 等 RSC 语法的解析与转换。
rspack.config.mjs
const jsxRule = {
test: /\.jsx$/,
use: {
loader: 'builtin:swc-loader',
options: {
jsc: {
parser: {
syntax: 'ecmascript',
jsx: true,
},
},
},
rspackExperiments: {
reactServerComponents: true,
},
},
type: 'javascript/auto',
};
const tsxRule = {
test: /\.tsx$/,
use: {
loader: 'builtin:swc-loader',
options: {
jsc: {
parser: {
syntax: 'typescript',
tsx: true,
},
},
},
rspackExperiments: {
reactServerComponents: true,
},
},
type: 'javascript/auto',
};
export default [
{
target: 'web',
module: {
rules: [jsxRule, tsxRule],
},
},
{
target: 'node',
module: {
rules: [jsxRule, tsxRule],
},
},
];
Loader 会根据模块所属的 layer 对 "use client" 和 "use server" 指令执行不同的转换逻辑:
-
当模块属于 Layers.rsc(服务器组件环境)时,会调用 react-server-dom-rspack 进行转换:
"use client" 模块被转换为客户端引用(Client Reference)。
"use server" 模块被注册为 Server Action,使其能够响应来自客户端的远程调用。
-
当模块不属于 Layers.rsc(如客户端或 SSR 环境)时:
"use server":模块会转换为服务端引用(Server Reference)。
RSC 插件会依据 loader 识别出的指令信息区分客户端组件与服务器组件,并据此注入 Client 入口、收集 Server Action、生成 RSC 清单等。
开发服务器
RSC 需要同时处理客户端和服务器端的构建、响应 RSC 请求和服务器组件 HMR,Rspack 内置的 Dev Server 无法满足需求。你需要实现一个自定义开发服务器,以实现以下核心功能:
- 响应 RSC 请求:拦截并处理客户端发起的 RSC 请求,调用 Server Compiler 生成的产物执行渲染逻辑,并返回序列化的 RSC Payload(或 HTML 流)。
- 服务端运行时管理:将服务端产物运行在独立的上下文(如 Worker Threads 或子进程)中,以保证环境隔离。同时确保在服务端代码更新时,能够清理旧实例并重启以执行新代码。
- 服务器组件 HMR:服务端组件的构建变更后,通过 WebSocket 等通信机制通知浏览器。浏览器接收到信号后,应触发 RSC 重新请求,更新页面内容。
为实现服务器组件 HMR,Rspack 在 ServerPlugin 中提供了 onServerComponentChanges 钩子(构建完成后、若有服务器组件变更则调用)。在自定义开发服务器中可在此回调里通过 WebSocket 等方式通知浏览器重新请求 RSC 以更新页面。
rspack.config.mjs
export default [
// ...
{
target: 'node',
plugins: [
new ServerPlugin({
onServerComponentChanges() {
// 调用自定义 Server 的方法通知客户端刷新
},
}),
],
},
];