You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
React Router provides a set of APIs for integrating with RSC-compatible bundlers, allowing you to leverage [Server Components][react-server-components-doc] and [Server Functions][react-server-functions-doc] in your React Router applications.
24
24
25
+
If you're unfamiliar with these React features, we recommend reading the official [Server Components documentation][react-server-components-doc] before using React Router's RSC APIs.
26
+
27
+
RSC support is available in both Framework and Data Modes. For more information on the conceptual difference between these, see ["Picking a Mode"][picking-a-mode]. However, note that the APIs and features differ between RSC and non-RSC modes in ways that this guide will cover in more detail.
28
+
25
29
## Quick Start
26
30
27
31
The quickest way to get started is with one of our templates.
28
32
29
-
These templates come with React Router RSC APIs already configured with the respective bundler, offering you out of the box features such as:
33
+
These templates come with React Router RSC APIs already configured, offering you out of the box features such as:
- Server Functions (via [`"use server"`][use-server-docs] directive)
35
39
36
-
**Parcel Template**
40
+
### RSC Framework Mode Template
37
41
38
-
The [parcel template][parcel-rsc-template] uses the official React `react-server-dom-parcel` plugin.
42
+
The [RSC Framework Mode template][framework-rsc-template] uses the unstable React Router RSC Vite plugin along with the experimental [`@vitejs/plugin-rsc` plugin][vite-plugin-rsc].
Most APIs and features in RSC Framework Mode are the same as non-RSC Framework Mode, so this guide will focus on the differences.
67
+
68
+
### New React Router RSC Vite Plugin
69
+
70
+
RSC Framework Mode uses a different Vite plugin than non-RSC Framework Mode, currently exported as `unstable_reactRouterRSC`.
71
+
72
+
This new Vite plugin also has a peer dependency on the experimental `@vitejs/plugin-rsc` plugin. Note that the `@vitejs/plugin-rsc` plugin should be placed after the React Router RSC plugin in your Vite config.
The RSC Framework Mode server build file (`build/server/index.js`) now exports a `default` request handler function (`(request: Request) => Promise<Response>`) for document/data requests.
87
+
88
+
If needed, you can convert this into a [standard Node.js request listener][node-request-listener] for use with Node's built-in `http.createServer` function (or anything that supports it, e.g. [Express][express]) by using the `createRequestListener` function from [@remix-run/node-fetch-server][node-fetch-server].
In RSC Framework Mode, loaders and actions can now return React elements along with other data. These elements will only ever be rendered on the server.
114
+
115
+
```tsx
116
+
importtype { Route } from"./+types/route";
117
+
118
+
exportasyncfunction loader() {
119
+
return {
120
+
message: "Message from the server!",
121
+
element: <p>Element from the server!</p>,
122
+
};
123
+
}
124
+
125
+
exportdefaultfunction Route({
126
+
loaderData,
127
+
}:Route.ComponentProps) {
128
+
return (
129
+
<>
130
+
<h1>{loaderData.message}</h1>
131
+
{loaderData.element}
132
+
</>
133
+
);
134
+
}
135
+
```
136
+
137
+
If you need to use client-only features (e.g. [Hooks][hooks], event handlers) within React elements returned from loaders/actions, you'll need to extract components using these features into a [client module][use-client-docs]:
138
+
139
+
```tsx filename=src/routes/counter/counter.tsx
140
+
"use client";
141
+
142
+
exportfunction Counter() {
143
+
const [count, setCount] =useState(0);
144
+
return (
145
+
<buttononClick={() =>setCount(count+1)}>
146
+
Count: {count}
147
+
</button>
148
+
);
149
+
}
150
+
```
151
+
152
+
```tsx filename=src/routes/counter/route.tsx
153
+
importtype { Route } from"./+types/route";
154
+
import { Counter } from"./counter";
155
+
156
+
exportasyncfunction loader() {
157
+
return {
158
+
message: "Message from the server!",
159
+
element: (
160
+
<>
161
+
<p>Element from the server!</p>
162
+
<Counter />
163
+
</>
164
+
),
165
+
};
166
+
}
167
+
168
+
exportdefaultfunction Route({
169
+
loaderData,
170
+
}:Route.ComponentProps) {
171
+
return (
172
+
<>
173
+
<h1>{loaderData.message}</h1>
174
+
{loaderData.element}
175
+
</>
176
+
);
177
+
}
178
+
```
179
+
180
+
### Server Component Routes
181
+
182
+
If a route exports a `ServerComponent` instead of the typical `default` component export, this component along with other route components (`ErrorBoundary`, `HydrateFallback`, `Layout`) will be server components rather than the usual client components.
183
+
184
+
```tsx
185
+
importtype { Route } from"./+types/route";
186
+
import { Outlet } from"react-router";
187
+
import { getMessage } from"./message";
188
+
189
+
exportasyncfunction loader() {
190
+
return {
191
+
message: awaitgetMessage(),
192
+
};
193
+
}
194
+
195
+
exportfunction ServerComponent({
196
+
loaderData,
197
+
}:Route.ComponentProps) {
198
+
return (
199
+
<>
200
+
<h1>Server Component Route</h1>
201
+
<p>Message from the server: {loaderData.message}</p>
202
+
<Outlet />
203
+
</>
204
+
);
205
+
}
206
+
```
207
+
208
+
If you need to use client-only features (e.g. [Hooks][hooks], event handlers) within a server-first route, you'll need to extract components using these features into a [client module][use-client-docs]:
209
+
210
+
```tsx filename=src/routes/counter/counter.tsx
211
+
"use client";
212
+
213
+
exportfunction Counter() {
214
+
const [count, setCount] =useState(0);
215
+
return (
216
+
<buttononClick={() =>setCount(count+1)}>
217
+
Count: {count}
218
+
</button>
219
+
);
220
+
}
221
+
```
222
+
223
+
```tsx filename=src/routes/counter/route.tsx
224
+
import { Counter } from"./counter";
225
+
226
+
exportfunction ServerComponent() {
227
+
return (
228
+
<>
229
+
<h1>Counter</h1>
230
+
<Counter />
231
+
</>
232
+
);
233
+
}
234
+
```
235
+
236
+
### `.server`/`.client` Modules
237
+
238
+
To avoid confusion with RSC's `"use server"` and `"use client"` directives, support for [`.server` modules][server-modules] and [`.client` modules][client-modules] is no longer built-in when using RSC Framework Mode.
239
+
240
+
As an alternative solution that doesn't rely on file naming conventions, we recommend using the `"server-only"` and `"client-only"` imports provided by [`@vitejs/plugin-rsc`][vite-plugin-rsc]. For example, to ensure a module is never accidentally included in the client build, simply import from `"server-only"` as a side effect within your server-only module.
241
+
242
+
```ts filename=app/utils/db.ts
243
+
import"server-only";
244
+
245
+
// Rest of the module...
246
+
```
247
+
248
+
Note that while there are official npm packages [`server-only`][server-only-package] and [`client-only`][client-only-package] created by the React team, they don't need to be installed. `@vitejs/plugin-rsc` internally handles these imports and provides build-time validation instead of runtime errors.
249
+
250
+
If you'd like to quickly migrate existing code that relies on the `.server` and `.client` file naming conventions, we recommend using the [`vite-env-only` plugin][vite-env-only] directly. For example, to ensure `.server` modules aren't accidentally included in the client build:
MDX routes are supported in RSC Framework Mode when using `@mdx-js/rollup` v3.1.1+.
272
+
273
+
Note that any components exported from an MDX route must also be valid in RSC environments, meaning that they cannot use client-only features like [Hooks][hooks]. Any components that need to use these features should be extracted into a [client module][use-client-docs].
274
+
275
+
### Unsupported Config Options
276
+
277
+
For the initial unstable release, the following options from `react-router.config.ts` are not yet supported in RSC Framework Mode:
278
+
279
+
-`buildEnd`
280
+
-`prerender`
281
+
-`presets`
282
+
-`routeDiscovery`
283
+
-`serverBundles`
284
+
-`ssr: false` (SPA Mode)
285
+
-`future.unstable_splitRouteModules`
286
+
-`future.unstable_subResourceIntegrity`
287
+
288
+
Custom build entry files are also not yet supported.
289
+
290
+
## RSC Data Mode
291
+
292
+
The RSC Framework Mode APIs described above are built on top of lower-level RSC Data Mode APIs.
293
+
294
+
RSC Data Mode is missing some of the features of RSC Framework Mode (e.g. `routes.ts` config and file system routing, HMR and Hot Data Revalidation), but is more flexible and allows you to integrate with your own bundler and server abstractions.
53
295
54
296
### Configuring Routes
55
297
@@ -238,7 +480,7 @@ export default function Root() {
238
480
}
239
481
```
240
482
241
-
##Configuring RSC with React Router
483
+
### Bundler Configuration
242
484
243
485
React Router provides several APIs that allow you to easily integrate with RSC-compatible bundlers, useful if you are using React Router Data Mode to make your own [custom framework][custom-framework].
244
486
@@ -303,7 +545,7 @@ Relevant APIs:
303
545
304
546
### Parcel
305
547
306
-
See the [Parcel RSC docs][parcel-rsc-doc] for more information. You can also refer to our [Parcel RSC Parcel template][parcel-rsc-template] to see a working version.
548
+
See the [Parcel RSC docs][parcel-rsc-doc] for more information. You can also refer to our [Parcel RSC Data Mode template][parcel-rsc-template] to see a working version.
307
549
308
550
In addition to `react`, `react-dom`, and `react-router`, you'll need the following dependencies:
See the [Vite RSC docs][vite-rsc-doc] for more information. You can also refer to our [Vite RSC template][vite-rsc-template] to see a working version.
794
+
See the [@vitejs/plugin-rscdocs][vite-plugin-rsc] for more information. You can also refer to our [Vite RSC Data Mode template][vite-rsc-template] to see a working version.
553
795
554
796
In addition to `react`, `react-dom`, and `react-router`, you'll need the following dependencies:
0 commit comments