rsbuild-plugin-react-router 0.0.5 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +228 -3
- package/dist/906.js +1 -0
- package/dist/946.js +1 -0
- package/dist/babel.d.ts +2 -2
- package/dist/build-manifest.d.ts +19 -0
- package/dist/constants.d.ts +10 -3
- package/dist/export-utils.d.ts +7 -0
- package/dist/index.cjs +1824 -645
- package/dist/index.js +1594 -483
- package/dist/manifest.d.ts +18 -1
- package/dist/modify-browser-manifest.d.ts +7 -1
- package/dist/plugin-utils.d.ts +2 -0
- package/dist/prerender.d.ts +16 -0
- package/dist/react-router-config.d.ts +51 -0
- package/dist/route-chunks.d.ts +32 -0
- package/dist/route-config.d.ts +13 -0
- package/dist/rslib-runtime.js +23 -0
- package/dist/server-utils.d.ts +22 -6
- package/dist/ssr-externals.d.ts +1 -0
- package/dist/templates/entry.client.cjs +5 -7
- package/dist/templates/entry.client.js +5 -5
- package/dist/templates/entry.server.cjs +7 -6
- package/dist/templates/entry.server.js +10 -11
- package/dist/types.d.ts +6 -0
- package/dist/validation/validate-plugin-order.d.ts +9 -0
- package/dist/warnings/warn-on-client-source-maps.d.ts +6 -0
- package/package.json +46 -47
- package/dist/transform-route-federation.d.ts +0 -6
package/README.md
CHANGED
|
@@ -8,13 +8,17 @@ A Rsbuild plugin that provides seamless integration with React Router, supportin
|
|
|
8
8
|
|
|
9
9
|
## Features
|
|
10
10
|
|
|
11
|
+
|
|
11
12
|
- 🚀 Zero-config setup with sensible defaults
|
|
12
13
|
- 🔄 Automatic route generation from file system
|
|
13
14
|
- 🖥️ Server-Side Rendering (SSR) support
|
|
14
|
-
- 📱 Client-side navigation
|
|
15
|
+
- 📱 Client-side navigation with SPA mode (`ssr: false`)
|
|
16
|
+
- 📄 Static prerendering for hybrid static/dynamic sites
|
|
15
17
|
- 🛠️ TypeScript support out of the box
|
|
16
18
|
- 🔧 Customizable configuration
|
|
17
19
|
- 🎯 Support for route-level code splitting
|
|
20
|
+
- ☁️ Cloudflare Workers deployment support
|
|
21
|
+
- 🔗 Module Federation support (experimental)
|
|
18
22
|
|
|
19
23
|
## Installation
|
|
20
24
|
|
|
@@ -26,6 +30,18 @@ yarn add rsbuild-plugin-react-router
|
|
|
26
30
|
pnpm add rsbuild-plugin-react-router
|
|
27
31
|
```
|
|
28
32
|
|
|
33
|
+
## Local development
|
|
34
|
+
|
|
35
|
+
For the federation examples and Playwright e2e tests, use Node 22 and the
|
|
36
|
+
repo-pinned pnpm version:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
nvm install
|
|
40
|
+
nvm use
|
|
41
|
+
corepack enable
|
|
42
|
+
corepack prepare pnpm@9.15.3 --activate
|
|
43
|
+
```
|
|
44
|
+
|
|
29
45
|
## Usage
|
|
30
46
|
|
|
31
47
|
Add the plugin to your `rsbuild.config.ts`:
|
|
@@ -43,7 +59,7 @@ export default defineConfig(() => {
|
|
|
43
59
|
customServer: false,
|
|
44
60
|
// Optional: Specify server output format
|
|
45
61
|
serverOutput: "commonjs",
|
|
46
|
-
//Optional: enable experimental support for module federation
|
|
62
|
+
// Optional: enable experimental support for module federation
|
|
47
63
|
federation: false
|
|
48
64
|
}),
|
|
49
65
|
pluginReact()
|
|
@@ -78,9 +94,18 @@ pluginReactRouter({
|
|
|
78
94
|
*/
|
|
79
95
|
federation?: boolean
|
|
80
96
|
})
|
|
97
|
+
|
|
98
|
+
When Module Federation is enabled, configure your Federation plugin with
|
|
99
|
+
`experiments.asyncStartup: true` to avoid requiring entrypoint `import()` hacks.
|
|
100
|
+
See the Module Federation examples under `examples/federation`.
|
|
101
|
+
|
|
102
|
+
When Module Federation is enabled, some runtimes may expose server build exports
|
|
103
|
+
as async getters. The dev server resolves these exports automatically. For
|
|
104
|
+
production, use a custom server or an adapter that resolves async exports before
|
|
105
|
+
passing the build to React Router's request handler.
|
|
81
106
|
```
|
|
82
107
|
|
|
83
|
-
2. **React Router Configuration** (in `react-router.config
|
|
108
|
+
2. **React Router Configuration** (in `react-router.config.*`):
|
|
84
109
|
```ts
|
|
85
110
|
import type { Config } from '@react-router/dev/config';
|
|
86
111
|
|
|
@@ -91,6 +116,31 @@ export default {
|
|
|
91
116
|
*/
|
|
92
117
|
ssr: true,
|
|
93
118
|
|
|
119
|
+
/**
|
|
120
|
+
* The file name for the server build output.
|
|
121
|
+
* @default "index.js"
|
|
122
|
+
*/
|
|
123
|
+
serverBuildFile: "index.js",
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* The output format for the server build.
|
|
127
|
+
* Options: "esm" | "cjs"
|
|
128
|
+
* @default "esm"
|
|
129
|
+
*/
|
|
130
|
+
serverModuleFormat: "esm",
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Split server bundles by route branch (advanced).
|
|
134
|
+
*/
|
|
135
|
+
serverBundles: async ({ branch }) => branch[0]?.id ?? "main",
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Hook called after the build completes.
|
|
139
|
+
*/
|
|
140
|
+
buildEnd: async ({ buildManifest, reactRouterConfig }) => {
|
|
141
|
+
console.log(buildManifest, reactRouterConfig);
|
|
142
|
+
},
|
|
143
|
+
|
|
94
144
|
/**
|
|
95
145
|
* Build directory for output files
|
|
96
146
|
* @default 'build'
|
|
@@ -108,11 +158,116 @@ export default {
|
|
|
108
158
|
* @default '/'
|
|
109
159
|
*/
|
|
110
160
|
basename: '/my-app',
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* React Router future flags (optional).
|
|
164
|
+
* Example: split client route modules into separate chunks.
|
|
165
|
+
*/
|
|
166
|
+
future: {
|
|
167
|
+
v8_splitRouteModules: true,
|
|
168
|
+
},
|
|
111
169
|
} satisfies Config;
|
|
112
170
|
```
|
|
113
171
|
|
|
114
172
|
All configuration options are optional and will use sensible defaults if not specified.
|
|
115
173
|
|
|
174
|
+
### Config File Resolution
|
|
175
|
+
|
|
176
|
+
The plugin will look for `react-router.config` with any supported JS/TS extension, in this order:
|
|
177
|
+
|
|
178
|
+
- `react-router.config.tsx`
|
|
179
|
+
- `react-router.config.ts`
|
|
180
|
+
- `react-router.config.mts`
|
|
181
|
+
- `react-router.config.jsx`
|
|
182
|
+
- `react-router.config.js`
|
|
183
|
+
- `react-router.config.mjs`
|
|
184
|
+
|
|
185
|
+
If none are found, it falls back to defaults.
|
|
186
|
+
|
|
187
|
+
### Framework Mode
|
|
188
|
+
|
|
189
|
+
React Router "Framework Mode" is implemented as a Vite plugin, but this Rsbuild
|
|
190
|
+
plugin aims to provide equivalent **framework-mode behaviors** (typegen, Route
|
|
191
|
+
Module API types, route module splitting, SPA/SSR/prerender strategies) on top
|
|
192
|
+
of Rsbuild/Rspack.
|
|
193
|
+
|
|
194
|
+
In practice, you should be able to use the `@react-router/dev/*` config + routes
|
|
195
|
+
APIs, import generated `./+types/*` in route modules, and use the standard
|
|
196
|
+
`entry.client`/`entry.server` entrypoints like you would in the official setup.
|
|
197
|
+
|
|
198
|
+
### FAQ
|
|
199
|
+
|
|
200
|
+
#### rsbuild-plugin-react-router vs ModernJS
|
|
201
|
+
|
|
202
|
+
This plugin is a lightweight adapter to run React Router on Rsbuild. It does
|
|
203
|
+
not aim to replace ModernJS or its higher-level framework features. If your
|
|
204
|
+
goal is a full framework or advanced microfrontend support, ModernJS may be
|
|
205
|
+
a better fit.
|
|
206
|
+
|
|
207
|
+
### SPA Mode (`ssr: false`)
|
|
208
|
+
|
|
209
|
+
React Router's SPA Mode still requires a build-time server render of the root route to generate a hydratable `index.html` (this is how the official React Router Vite plugin works).
|
|
210
|
+
|
|
211
|
+
When `ssr: false`:
|
|
212
|
+
|
|
213
|
+
- The plugin builds both `web` and `node` internally.
|
|
214
|
+
- It generates `build/client/index.html` by running the server build once (requesting `basename` with the `X-React-Router-SPA-Mode: yes` header).
|
|
215
|
+
- It removes `build/server` after generating `index.html`, so the output is deployable as static assets.
|
|
216
|
+
|
|
217
|
+
**Important:** In SPA mode, use `clientLoader` instead of `loader` for data loading since there's no server at runtime.
|
|
218
|
+
|
|
219
|
+
### Static Prerendering
|
|
220
|
+
|
|
221
|
+
For static sites with multiple pages, you can prerender specific routes at build time:
|
|
222
|
+
|
|
223
|
+
```ts
|
|
224
|
+
// react-router.config.ts
|
|
225
|
+
import type { Config } from '@react-router/dev/config';
|
|
226
|
+
|
|
227
|
+
export default {
|
|
228
|
+
ssr: false,
|
|
229
|
+
prerender: [
|
|
230
|
+
'/',
|
|
231
|
+
'/about',
|
|
232
|
+
'/docs',
|
|
233
|
+
'/docs/getting-started',
|
|
234
|
+
'/docs/advanced',
|
|
235
|
+
'/projects',
|
|
236
|
+
],
|
|
237
|
+
} satisfies Config;
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
When `prerender` is specified:
|
|
241
|
+
|
|
242
|
+
- Each path in the array is rendered at build time
|
|
243
|
+
- Static HTML files are generated for each route (e.g., `/about` → `build/client/about/index.html`)
|
|
244
|
+
- The server build is removed after prerendering for static deployment
|
|
245
|
+
- Non-prerendered routes fall back to client-side routing
|
|
246
|
+
|
|
247
|
+
You can also use `prerender: true` to prerender all static routes automatically.
|
|
248
|
+
|
|
249
|
+
`prerender` can also be a function:
|
|
250
|
+
|
|
251
|
+
```ts
|
|
252
|
+
export default {
|
|
253
|
+
ssr: false,
|
|
254
|
+
prerender: ({ getStaticPaths }) =>
|
|
255
|
+
getStaticPaths().filter(path => path !== '/admin'),
|
|
256
|
+
} satisfies Config;
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
For large sites, you can tune prerender concurrency:
|
|
260
|
+
|
|
261
|
+
```ts
|
|
262
|
+
export default {
|
|
263
|
+
ssr: false,
|
|
264
|
+
prerender: {
|
|
265
|
+
paths: ['/','/about'],
|
|
266
|
+
unstable_concurrency: 4,
|
|
267
|
+
},
|
|
268
|
+
} satisfies Config;
|
|
269
|
+
```
|
|
270
|
+
|
|
116
271
|
### Default Configuration Values
|
|
117
272
|
|
|
118
273
|
If no configuration is provided, the following defaults will be used:
|
|
@@ -187,6 +342,7 @@ Route components support the following exports:
|
|
|
187
342
|
- `Layout` - Layout component
|
|
188
343
|
- `clientLoader` - Client-side data loading
|
|
189
344
|
- `clientAction` - Client-side form actions
|
|
345
|
+
- `clientMiddleware` - Client-side middleware
|
|
190
346
|
- `handle` - Route handle
|
|
191
347
|
- `links` - Prefetch links
|
|
192
348
|
- `meta` - Route meta data
|
|
@@ -195,8 +351,24 @@ Route components support the following exports:
|
|
|
195
351
|
#### Server-side Exports
|
|
196
352
|
- `loader` - Server-side data loading
|
|
197
353
|
- `action` - Server-side form actions
|
|
354
|
+
- `middleware` - Server-side middleware
|
|
198
355
|
- `headers` - HTTP headers
|
|
199
356
|
|
|
357
|
+
### Client/Server-only Modules
|
|
358
|
+
|
|
359
|
+
- Files ending in `.client.*` are treated as client-only. Their exports are
|
|
360
|
+
stubbed to `undefined` in the server build, so they are safe to import from
|
|
361
|
+
route components for browser-only behavior.
|
|
362
|
+
- Files ending in `.server.*` are server-only. If they are imported by code
|
|
363
|
+
compiled for the web environment, the build will fail with a clear error.
|
|
364
|
+
Keep `.server` imports in server entrypoints or other server-only code.
|
|
365
|
+
|
|
366
|
+
### Asset Prefix
|
|
367
|
+
|
|
368
|
+
If you configure `output.assetPrefix` in Rsbuild, the plugin uses that value
|
|
369
|
+
for the React Router browser manifest and server build `publicPath` so asset
|
|
370
|
+
URLs resolve correctly when serving from a CDN or sub-path.
|
|
371
|
+
|
|
200
372
|
## Custom Server Setup
|
|
201
373
|
|
|
202
374
|
The plugin supports two ways to handle server-side rendering:
|
|
@@ -479,6 +651,59 @@ The plugin automatically:
|
|
|
479
651
|
- Handles route-based code splitting
|
|
480
652
|
- Manages client and server builds
|
|
481
653
|
|
|
654
|
+
## React Router Framework Mode
|
|
655
|
+
|
|
656
|
+
React Router "Framework Mode" wraps Data Mode using a Vite plugin. This Rsbuild
|
|
657
|
+
plugin aims to match the important behaviors without depending on Vite:
|
|
658
|
+
|
|
659
|
+
- Typegen + Route Module API types (`./+types/*`)
|
|
660
|
+
- Route module splitting (`future.v8_splitRouteModules`)
|
|
661
|
+
- SPA mode (`ssr: false`), SSR mode, and static prerendering (`prerender`)
|
|
662
|
+
|
|
663
|
+
Some Vite-specific integrations (for example Vite's environment API + critical
|
|
664
|
+
CSS endpoint) are not supported 1:1.
|
|
665
|
+
|
|
666
|
+
## Examples
|
|
667
|
+
|
|
668
|
+
The repository includes several examples demonstrating different use cases:
|
|
669
|
+
|
|
670
|
+
| Example | Description | Port | Command |
|
|
671
|
+
|---------|-------------|------|---------|
|
|
672
|
+
| [default-template](./examples/default-template) | Standard SSR setup with React Router | 3000 | `pnpm dev` |
|
|
673
|
+
| [spa-mode](./examples/spa-mode) | Single Page Application (`ssr: false`) | 3001 | `pnpm dev` |
|
|
674
|
+
| [prerender](./examples/prerender) | Static prerendering for multiple routes | 3002 | `pnpm dev` |
|
|
675
|
+
| [custom-node-server](./examples/custom-node-server) | Custom Express server with SSR | 3003 | `pnpm dev` |
|
|
676
|
+
| [cloudflare](./examples/cloudflare) | Cloudflare Workers deployment | 3004 | `pnpm dev` |
|
|
677
|
+
| [client-only](./examples/client-only) | `.client` modules with SSR hydration | 3010 | `pnpm dev` |
|
|
678
|
+
| [epic-stack](./examples/epic-stack) | Full-featured Epic Stack example | 3005 | `pnpm dev` |
|
|
679
|
+
| [federation/epic-stack](./examples/federation/epic-stack) | Module Federation host | 3006 | `pnpm dev` |
|
|
680
|
+
| [federation/epic-stack-remote](./examples/federation/epic-stack-remote) | Module Federation remote | 3007 | `pnpm dev` |
|
|
681
|
+
|
|
682
|
+
Each example has unique ports configured to allow running multiple examples simultaneously.
|
|
683
|
+
|
|
684
|
+
### Running Examples
|
|
685
|
+
|
|
686
|
+
```bash
|
|
687
|
+
# Install dependencies
|
|
688
|
+
pnpm install
|
|
689
|
+
|
|
690
|
+
# Build the plugin
|
|
691
|
+
pnpm build
|
|
692
|
+
|
|
693
|
+
# Run any example
|
|
694
|
+
cd examples/default-template
|
|
695
|
+
pnpm dev
|
|
696
|
+
```
|
|
697
|
+
|
|
698
|
+
### Running E2E Tests
|
|
699
|
+
|
|
700
|
+
Each example includes Playwright e2e tests:
|
|
701
|
+
|
|
702
|
+
```bash
|
|
703
|
+
cd examples/default-template
|
|
704
|
+
pnpm test:e2e
|
|
705
|
+
```
|
|
706
|
+
|
|
482
707
|
## License
|
|
483
708
|
|
|
484
709
|
MIT
|
package/dist/906.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { ServerRouter, createRequestHandler, matchRoutes } from "react-router";
|
package/dist/946.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { StrictMode, createElement, startTransition } from "react";
|
package/dist/babel.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { types as Babel } from '@babel/core';
|
|
|
2
2
|
import { type ParseResult, parse } from '@babel/parser';
|
|
3
3
|
import type { NodePath } from '@babel/traverse';
|
|
4
4
|
import * as t from '@babel/types';
|
|
5
|
-
declare const traverse: typeof import(
|
|
6
|
-
declare const generate: typeof import(
|
|
5
|
+
declare const traverse: typeof import('@babel/traverse').default;
|
|
6
|
+
declare const generate: typeof import('@babel/generator').default;
|
|
7
7
|
export { traverse, generate, parse, t };
|
|
8
8
|
export type { Babel, NodePath, ParseResult };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Config } from './react-router-config.js';
|
|
2
|
+
import type { Route } from './types.js';
|
|
3
|
+
type BuildManifest = {
|
|
4
|
+
routes: Record<string, Route>;
|
|
5
|
+
} | {
|
|
6
|
+
routes: Record<string, Route>;
|
|
7
|
+
serverBundles: Record<string, {
|
|
8
|
+
id: string;
|
|
9
|
+
file: string;
|
|
10
|
+
}>;
|
|
11
|
+
routeIdToServerBundleId: Record<string, string>;
|
|
12
|
+
};
|
|
13
|
+
export declare const getBuildManifest: ({ reactRouterConfig, routes, rootDirectory, }: {
|
|
14
|
+
reactRouterConfig: Required<Pick<Config, "appDirectory" | "buildDirectory" | "serverBuildFile" | "future">> & Pick<Config, "serverBundles">;
|
|
15
|
+
routes: Record<string, Route>;
|
|
16
|
+
rootDirectory: string;
|
|
17
|
+
}) => Promise<BuildManifest | undefined>;
|
|
18
|
+
export declare const getRoutesByServerBundleId: (buildManifest: BuildManifest | undefined) => Record<string, Record<string, Route>>;
|
|
19
|
+
export {};
|
package/dist/constants.d.ts
CHANGED
|
@@ -1,22 +1,29 @@
|
|
|
1
1
|
export declare const PLUGIN_NAME = "rsbuild:react-router";
|
|
2
|
-
export declare const JS_EXTENSIONS: readonly [".tsx", ".ts", ".jsx", ".js", ".mjs"];
|
|
2
|
+
export declare const JS_EXTENSIONS: readonly [".tsx", ".ts", ".jsx", ".js", ".mjs", ".mts"];
|
|
3
3
|
export declare const JS_LOADERS: {
|
|
4
4
|
readonly '.ts': "ts";
|
|
5
5
|
readonly '.tsx': "tsx";
|
|
6
6
|
readonly '.js': "js";
|
|
7
7
|
readonly '.jsx': "jsx";
|
|
8
|
+
readonly '.mjs': "js";
|
|
9
|
+
readonly '.mts': "ts";
|
|
8
10
|
};
|
|
9
|
-
export declare const
|
|
10
|
-
export declare const
|
|
11
|
+
export declare const BUILD_CLIENT_ROUTE_QUERY_STRING = "?__react-router-build-client-route";
|
|
12
|
+
export declare const SERVER_ONLY_ROUTE_EXPORTS: readonly ["loader", "action", "middleware", "headers"];
|
|
13
|
+
export declare const CLIENT_NON_COMPONENT_EXPORTS: readonly ["clientAction", "clientLoader", "clientMiddleware", "handle", "meta", "links", "shouldRevalidate"];
|
|
14
|
+
export declare const CLIENT_COMPONENT_EXPORTS: readonly ["default", "ErrorBoundary", "HydrateFallback", "Layout"];
|
|
15
|
+
export declare const CLIENT_ROUTE_EXPORTS: readonly ((typeof CLIENT_NON_COMPONENT_EXPORTS)[number] | (typeof CLIENT_COMPONENT_EXPORTS)[number])[];
|
|
11
16
|
export declare const NAMED_COMPONENT_EXPORTS: readonly ["HydrateFallback", "ErrorBoundary"];
|
|
12
17
|
export declare const SERVER_EXPORTS: {
|
|
13
18
|
readonly loader: "loader";
|
|
14
19
|
readonly action: "action";
|
|
20
|
+
readonly middleware: "middleware";
|
|
15
21
|
readonly headers: "headers";
|
|
16
22
|
};
|
|
17
23
|
export declare const CLIENT_EXPORTS: {
|
|
18
24
|
readonly clientAction: "clientAction";
|
|
19
25
|
readonly clientLoader: "clientLoader";
|
|
26
|
+
readonly clientMiddleware: "clientMiddleware";
|
|
20
27
|
readonly default: "default";
|
|
21
28
|
readonly ErrorBoundary: "ErrorBoundary";
|
|
22
29
|
readonly handle: "handle";
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const transformToEsm: (code: string, resourcePath: string) => Promise<string>;
|
|
2
|
+
export declare const getExportNames: (code: string) => Promise<string[]>;
|
|
3
|
+
export declare const getExportNamesAndExportAll: (code: string) => Promise<{
|
|
4
|
+
exportNames: string[];
|
|
5
|
+
exportAllModules: string[];
|
|
6
|
+
}>;
|
|
7
|
+
export declare const getRouteModuleExports: (resourcePath: string) => Promise<string[]>;
|