rsbuild-plugin-react-router 0.5.0 → 0.6.0
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 +58 -208
- package/dist/511.js +370 -331
- package/dist/build-output-transforms.d.ts +30 -6
- package/dist/classic-mode.d.ts +56 -0
- package/dist/config-imports.d.ts +8 -2
- package/dist/constants.d.ts +3 -0
- package/dist/dev-background-resources.d.ts +3 -1
- package/dist/dev-generation.d.ts +2 -3
- package/dist/dev-hmr.d.ts +8 -2
- package/dist/dev-runtime-controller.d.ts +6 -1
- package/dist/dev-source-maps.d.ts +4 -0
- package/dist/effect-runtime.d.ts +17 -5
- package/dist/entry-paths.d.ts +16 -0
- package/dist/environment-output.d.ts +6 -0
- package/dist/export-utils.d.ts +2 -1
- package/dist/index.cjs +3957 -2208
- package/dist/index.d.ts +3 -1
- package/dist/index.js +3470 -1793
- package/dist/lazy-compilation-prewarm.d.ts +8 -5
- package/dist/manifest.d.ts +16 -4
- package/dist/mode-plan.d.ts +82 -0
- package/dist/modify-browser-manifest.d.ts +8 -4
- package/dist/plugin-utils.d.ts +27 -1
- package/dist/prerender-build.d.ts +5 -5
- package/dist/prerender.d.ts +1 -5
- package/dist/react-router-config.d.ts +11 -3
- package/dist/route-artifacts.d.ts +4 -2
- package/dist/route-chunks.d.ts +2 -1
- package/dist/route-component-transform.d.ts +0 -2
- package/dist/route-export-pruning.d.ts +4 -1
- package/dist/route-imports.d.ts +18 -0
- package/dist/route-transform-tasks.d.ts +5 -0
- package/dist/route-watch.d.ts +11 -6
- package/dist/rsc-dev-server.d.ts +26 -0
- package/dist/rsc-prerender.d.ts +54 -0
- package/dist/rsc-route-config.d.ts +6 -0
- package/dist/rsc-route-exports.d.ts +15 -0
- package/dist/rsc-route-transform-loader.cjs +43 -0
- package/dist/rsc-route-transform-loader.d.ts +30 -0
- package/dist/rsc-route-transform-loader.js +16 -0
- package/dist/rsc-route-transform-registration.d.ts +12 -0
- package/dist/rsc-route-transforms.d.ts +21 -0
- package/dist/rsc-support.d.ts +23 -0
- package/dist/rsc-virtual-modules.d.ts +19 -0
- package/dist/server-build-plan.d.ts +2 -1
- package/dist/server-build-resolution.d.ts +1 -2
- package/dist/server-utils.d.ts +4 -5
- package/dist/ssr-asset-relocation.d.ts +98 -0
- package/dist/templates/entry.rsc.client.d.ts +1 -0
- package/dist/templates/entry.rsc.client.js +61 -0
- package/dist/templates/entry.rsc.d.ts +9 -0
- package/dist/templates/entry.rsc.js +38 -0
- package/dist/templates/entry.rsc.ssr.d.ts +4 -0
- package/dist/templates/entry.rsc.ssr.js +24 -0
- package/dist/typegen.d.ts +4 -2
- package/dist/types.d.ts +30 -1
- package/package.json +69 -14
- package/src/build-output-transforms.ts +155 -21
- package/src/classic-mode.ts +253 -0
- package/src/config-imports.ts +153 -6
- package/src/constants.ts +6 -2
- package/src/dev-background-resources.ts +46 -85
- package/src/dev-generation.ts +52 -33
- package/src/dev-hmr.ts +112 -80
- package/src/dev-runtime-artifacts.ts +11 -12
- package/src/dev-runtime-controller.ts +75 -85
- package/src/dev-runtime-session.ts +14 -18
- package/src/dev-server.ts +2 -0
- package/src/dev-source-maps.ts +257 -0
- package/src/effect-runtime.ts +105 -57
- package/src/entry-paths.ts +80 -0
- package/src/environment-output.ts +55 -0
- package/src/export-utils.ts +15 -11
- package/src/index.ts +661 -496
- package/src/lazy-compilation-prewarm.ts +20 -4
- package/src/manifest.ts +157 -82
- package/src/mode-plan.ts +367 -0
- package/src/modify-browser-manifest.ts +130 -124
- package/src/plugin-utils.ts +103 -39
- package/src/prerender-build.ts +82 -104
- package/src/prerender.ts +23 -24
- package/src/react-router-config.ts +72 -26
- package/src/route-artifacts.ts +96 -66
- package/src/route-chunks.ts +167 -51
- package/src/route-component-transform.ts +14 -21
- package/src/route-export-pruning.ts +4 -3
- package/src/route-imports.ts +100 -0
- package/src/route-transform-tasks.ts +39 -25
- package/src/route-watch.ts +166 -188
- package/src/rsc-dev-server.ts +112 -0
- package/src/rsc-prerender.ts +362 -0
- package/src/rsc-route-config.ts +175 -0
- package/src/rsc-route-exports.ts +67 -0
- package/src/rsc-route-transform-loader.ts +65 -0
- package/src/rsc-route-transform-registration.ts +145 -0
- package/src/rsc-route-transforms.ts +995 -0
- package/src/rsc-runtime.d.ts +143 -0
- package/src/rsc-support.ts +116 -0
- package/src/rsc-virtual-modules.ts +113 -0
- package/src/server-build-plan.ts +14 -3
- package/src/server-build-resolution.ts +37 -47
- package/src/server-utils.ts +21 -35
- package/src/ssr-asset-relocation.ts +183 -0
- package/src/ssr-externals.ts +8 -26
- package/src/templates/entry.rsc.client.tsx +168 -0
- package/src/templates/entry.rsc.ssr.tsx +45 -0
- package/src/templates/entry.rsc.tsx +80 -0
- package/src/typegen.ts +40 -23
- package/src/types.ts +39 -1
- package/src/warnings/warn-on-client-source-maps.ts +6 -10
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export default function(source, map) {
|
|
2
|
+
let callback = this.async(), transform = this._compiler?.__reactRouterRscRouteTransform;
|
|
3
|
+
transform ? transform({
|
|
4
|
+
code: source.toString(),
|
|
5
|
+
resource: this.resource,
|
|
6
|
+
resourcePath: this.resourcePath,
|
|
7
|
+
resourceQuery: this.resourceQuery,
|
|
8
|
+
environment: {
|
|
9
|
+
name: this.getOptions().environmentName
|
|
10
|
+
}
|
|
11
|
+
}).then((result)=>{
|
|
12
|
+
callback(null, result.code, result.map ?? map);
|
|
13
|
+
}).catch((error)=>{
|
|
14
|
+
callback(error instanceof Error ? error : Error(String(error)));
|
|
15
|
+
}) : callback(null, source, map);
|
|
16
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { RsbuildPlugin } from '@rsbuild/core';
|
|
2
|
+
import type { RouteChunkCache, RouteChunkConfig } from './route-chunks.js';
|
|
3
|
+
import type { Route } from './types.js';
|
|
4
|
+
import type { ReactRouterPerformanceProfiler } from './performance.js';
|
|
5
|
+
export declare const registerReactRouterRscRouteTransforms: ({ api, isBuild, performanceProfiler, routeByFilePath, routeChunkCache, routeChunkConfig, }: {
|
|
6
|
+
api: Parameters<RsbuildPlugin["setup"]>[0];
|
|
7
|
+
isBuild: boolean;
|
|
8
|
+
performanceProfiler: Pick<ReactRouterPerformanceProfiler, "record">;
|
|
9
|
+
routeByFilePath: Map<string, Route>;
|
|
10
|
+
routeChunkCache: RouteChunkCache;
|
|
11
|
+
routeChunkConfig: RouteChunkConfig;
|
|
12
|
+
}) => void;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { generate } from './yuku.js';
|
|
2
|
+
import { type RouteChunkCache, type RouteChunkConfig } from './route-chunks.js';
|
|
3
|
+
import type { Route } from './types.js';
|
|
4
|
+
type RscRouteTransformOptions = {
|
|
5
|
+
code: string;
|
|
6
|
+
resourcePath: string;
|
|
7
|
+
resourceQuery?: string;
|
|
8
|
+
isRootRoute: boolean;
|
|
9
|
+
routeId: string;
|
|
10
|
+
routeByFilePath?: ReadonlyMap<string, Route>;
|
|
11
|
+
routeChunkCache: RouteChunkCache;
|
|
12
|
+
routeChunkConfig: RouteChunkConfig;
|
|
13
|
+
isServerEnvironment: boolean;
|
|
14
|
+
isDev: boolean;
|
|
15
|
+
};
|
|
16
|
+
type RscRouteTransformResult = {
|
|
17
|
+
code: string;
|
|
18
|
+
map: null | ReturnType<typeof generate>['map'];
|
|
19
|
+
};
|
|
20
|
+
export declare const transformRscRouteModule: (options: RscRouteTransformOptions) => Promise<RscRouteTransformResult>;
|
|
21
|
+
export {};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { RsbuildPlugin } from '@rsbuild/core';
|
|
2
|
+
import type { Config } from './react-router-config.js';
|
|
3
|
+
import type { PluginOptions } from './types.js';
|
|
4
|
+
type RscPluginOptions = Exclude<NonNullable<PluginOptions['rsc']>, boolean>;
|
|
5
|
+
type RscUnsupportedConfig = Pick<Config, 'buildEnd' | 'future' | 'presets' | 'serverBundles' | 'subResourceIntegrity'>;
|
|
6
|
+
export declare const assertReactRouterRscConfigSupport: ({ pluginName, userConfig, }: {
|
|
7
|
+
pluginName: string;
|
|
8
|
+
userConfig: RscUnsupportedConfig;
|
|
9
|
+
}) => void;
|
|
10
|
+
export declare const assertReactRouterRscSupport: ({ pluginName, resolvePackagePath, }: {
|
|
11
|
+
pluginName: string;
|
|
12
|
+
resolvePackagePath: (specifier: string) => string | undefined;
|
|
13
|
+
}) => void;
|
|
14
|
+
export declare const setupReactRouterRscPlugin: ({ api, entryRscPath, entrySsrPath, pluginName, rsc, }: {
|
|
15
|
+
api: Parameters<RsbuildPlugin["setup"]>[0];
|
|
16
|
+
entryRscPath: string;
|
|
17
|
+
entrySsrPath: string;
|
|
18
|
+
pluginName: string;
|
|
19
|
+
rsc: RscPluginOptions;
|
|
20
|
+
}) => Promise<void>;
|
|
21
|
+
export { createReactRouterRscDevServerSetup } from './rsc-dev-server.js';
|
|
22
|
+
export { registerReactRouterRscRouteTransforms } from './rsc-route-transform-registration.js';
|
|
23
|
+
export { createReactRouterRscResolveAliases, createReactRouterRscVirtualModules, } from './rsc-virtual-modules.js';
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Config } from './react-router-config.js';
|
|
2
|
+
import type { Route } from './types.js';
|
|
3
|
+
type RscVirtualModulesOptions = {
|
|
4
|
+
allowedActionOrigins: string[] | undefined;
|
|
5
|
+
appDirectory: string;
|
|
6
|
+
basename: string;
|
|
7
|
+
buildDirectory: string;
|
|
8
|
+
isBuild: boolean;
|
|
9
|
+
/** Resolved web `output.distPath.js` segment, e.g. `static/js`. */
|
|
10
|
+
jsDistPath: string;
|
|
11
|
+
outputClientPath: string;
|
|
12
|
+
publicPath: string;
|
|
13
|
+
routeDiscovery: Config['routeDiscovery'];
|
|
14
|
+
routes: Record<string, Route>;
|
|
15
|
+
ssr: boolean;
|
|
16
|
+
};
|
|
17
|
+
export declare const createReactRouterRscResolveAliases: (rootPath: string) => Record<string, string>;
|
|
18
|
+
export declare const createReactRouterRscVirtualModules: ({ allowedActionOrigins, appDirectory, basename, buildDirectory, isBuild, jsDistPath, outputClientPath, publicPath, routeDiscovery, routes, ssr, }: RscVirtualModulesOptions) => Record<string, string>;
|
|
19
|
+
export {};
|
|
@@ -12,11 +12,12 @@ export declare const createReactRouterServerBuildPlan: ({ routesByServerBundleId
|
|
|
12
12
|
serverBuildFile: string | undefined;
|
|
13
13
|
defaultEntryName: string;
|
|
14
14
|
}) => ReactRouterServerBuildPlan;
|
|
15
|
-
export declare const createReactRouterNodeEntries: ({ hasServerApp, isBuild, serverAppPath, entryServerPath, defaultEntryName, serverBundleEntries, }: {
|
|
15
|
+
export declare const createReactRouterNodeEntries: ({ hasServerApp, isBuild, serverAppPath, entryServerPath, serverBuildFile, defaultEntryName, serverBundleEntries, }: {
|
|
16
16
|
hasServerApp: boolean;
|
|
17
17
|
isBuild: boolean;
|
|
18
18
|
serverAppPath: string;
|
|
19
19
|
entryServerPath: string;
|
|
20
|
+
serverBuildFile: string | undefined;
|
|
20
21
|
defaultEntryName: string;
|
|
21
22
|
serverBundleEntries: readonly ReactRouterServerBundleEntry[];
|
|
22
23
|
}) => Record<string, string>;
|
|
@@ -1,3 +1,2 @@
|
|
|
1
|
-
import * as Effect from 'effect/Effect';
|
|
2
1
|
import type { ServerBuild } from 'react-router';
|
|
3
|
-
export declare function
|
|
2
|
+
export declare function resolveServerBuildModule(buildModule: unknown, source: string): Promise<ServerBuild>;
|
package/dist/server-utils.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ServerBuild } from 'react-router';
|
|
2
|
+
import { resolveServerBuildModule } from './server-build-resolution.js';
|
|
2
3
|
import type { Route } from './types.js';
|
|
3
4
|
/**
|
|
4
5
|
* Generates the server build template string.
|
|
@@ -13,6 +14,7 @@ interface ServerBuildOptions {
|
|
|
13
14
|
basename: string;
|
|
14
15
|
appDirectory: string;
|
|
15
16
|
ssr: boolean;
|
|
17
|
+
isSpaMode: boolean;
|
|
16
18
|
future?: unknown;
|
|
17
19
|
allowedActionOrigins?: string[];
|
|
18
20
|
prerender?: string[];
|
|
@@ -31,9 +33,6 @@ interface ServerBuildOptions {
|
|
|
31
33
|
* @param options Build options
|
|
32
34
|
* @returns The generated module content as a string
|
|
33
35
|
*/
|
|
34
|
-
declare function generateServerBuild(routes: Record<string, Route>, options: ServerBuildOptions
|
|
35
|
-
|
|
36
|
-
}): string;
|
|
37
|
-
export declare function resolveServerBuildModule(buildModule: unknown, source: string): Promise<ServerBuild>;
|
|
36
|
+
export declare function generateServerBuild(routes: Record<string, Route>, options: ServerBuildOptions): string;
|
|
37
|
+
export { resolveServerBuildModule };
|
|
38
38
|
export declare function resolveReactRouterServerBuild(buildModule: unknown): Promise<ServerBuild>;
|
|
39
|
-
export { generateServerBuild };
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Relocation of server-only static assets to the client build.
|
|
3
|
+
*
|
|
4
|
+
* In React Router framework mode a route's server-only code (a loader or a
|
|
5
|
+
* `.server` module) can import an asset — for example
|
|
6
|
+
* `import txtUrl from "./file.txt?url"` or a `.css?url` file. The imported URL
|
|
7
|
+
* is returned to the client (e.g. as loader data) and fetched from the client
|
|
8
|
+
* build directory at runtime, so the asset file must exist under
|
|
9
|
+
* `build/client` even though only the node/server compilation referenced it.
|
|
10
|
+
*
|
|
11
|
+
* Rspack emits these assets into the server output (`build/server/static/...`)
|
|
12
|
+
* and never into the client output. This module mirrors upstream React
|
|
13
|
+
* Router's Vite plugin, which internally enables `ssrEmitAssets` and then, in
|
|
14
|
+
* the SSR `writeBundle` hook, moves server-emitted static assets into the
|
|
15
|
+
* client assets directory and strips them from the server build
|
|
16
|
+
* (`react-router-dev/vite/plugin.ts`). Here the equivalent runs inside the
|
|
17
|
+
* node compilation's `processAssets` hook: static assets are written into the
|
|
18
|
+
* client output at the same public path and deleted from the server
|
|
19
|
+
* compilation so the server build never ships duplicate static files.
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* The subset of an Rspack asset info that identifies static assets emitted by
|
|
23
|
+
* asset modules (`asset/resource`) and the CSS pipeline.
|
|
24
|
+
*/
|
|
25
|
+
export interface RelocatableAssetInfo {
|
|
26
|
+
/**
|
|
27
|
+
* Set by Rspack for assets produced from a source module (asset modules and
|
|
28
|
+
* extracted CSS). JavaScript chunks and generated files such as
|
|
29
|
+
* `package.json` do not carry a `sourceFilename`.
|
|
30
|
+
*/
|
|
31
|
+
sourceFilename?: string;
|
|
32
|
+
/**
|
|
33
|
+
* Set for JavaScript chunk assets. Static assets never set this, so it is
|
|
34
|
+
* used to keep code-split JS in the server build.
|
|
35
|
+
*/
|
|
36
|
+
javascriptModule?: boolean;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* The minimal compilation surface needed to collect and relocate assets. Kept
|
|
40
|
+
* narrow so the logic can be unit-tested without a real Rspack compilation.
|
|
41
|
+
*/
|
|
42
|
+
export interface RelocatableAssetCompilation {
|
|
43
|
+
assets: Record<string, unknown>;
|
|
44
|
+
getAsset(name: string): {
|
|
45
|
+
name: string;
|
|
46
|
+
source: {
|
|
47
|
+
buffer(): Buffer;
|
|
48
|
+
};
|
|
49
|
+
info: RelocatableAssetInfo;
|
|
50
|
+
} | undefined | void;
|
|
51
|
+
deleteAsset(name: string): void;
|
|
52
|
+
}
|
|
53
|
+
export interface CollectedServerAsset {
|
|
54
|
+
/** The public path of the asset, relative to the compilation output root. */
|
|
55
|
+
name: string;
|
|
56
|
+
source: {
|
|
57
|
+
buffer(): Buffer;
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Determine whether an emitted asset is a static asset that must live in the
|
|
62
|
+
* client build. Static assets (asset modules and CSS) carry a `sourceFilename`
|
|
63
|
+
* and are not JavaScript chunks. Code-split JavaScript is intentionally
|
|
64
|
+
* excluded so it remains in the server build.
|
|
65
|
+
*/
|
|
66
|
+
export declare const isRelocatableServerAsset: (info: RelocatableAssetInfo | undefined) => boolean;
|
|
67
|
+
/**
|
|
68
|
+
* Collect the server-only static assets from a node compilation. Returns them
|
|
69
|
+
* in stable (sorted) order so callers and tests see deterministic output.
|
|
70
|
+
*/
|
|
71
|
+
export declare const collectRelocatableServerAssets: (compilation: RelocatableAssetCompilation) => CollectedServerAsset[];
|
|
72
|
+
export interface RelocateServerAssetsResult {
|
|
73
|
+
/** Assets written into the client output because they were missing or stale. */
|
|
74
|
+
written: string[];
|
|
75
|
+
/**
|
|
76
|
+
* Assets that already existed in the client output. They are still removed
|
|
77
|
+
* from the server build but not rewritten.
|
|
78
|
+
*/
|
|
79
|
+
skipped: string[];
|
|
80
|
+
}
|
|
81
|
+
export declare const relocateServerAssetsToClient: ({ compilation, outputClientPath, relocatedDestinations, existsSyncFn, mkdirFn, readFileFn, renameFn, rmFn, writeFileFn, }: {
|
|
82
|
+
compilation: RelocatableAssetCompilation;
|
|
83
|
+
outputClientPath: string;
|
|
84
|
+
/**
|
|
85
|
+
* Destination content digests already handled by a previous compilation
|
|
86
|
+
* (dev rebuilds, serverBundles). Stable dev filenames can carry changed
|
|
87
|
+
* bytes, so the cache is keyed by path and digest rather than path alone.
|
|
88
|
+
*/
|
|
89
|
+
relocatedDestinations?: Map<string, string>;
|
|
90
|
+
existsSyncFn?: (path: string) => boolean;
|
|
91
|
+
mkdirFn?: (dir: string) => Promise<unknown>;
|
|
92
|
+
readFileFn?: (path: string) => Promise<Buffer>;
|
|
93
|
+
renameFn?: (oldPath: string, newPath: string) => Promise<void>;
|
|
94
|
+
rmFn?: (path: string, options: {
|
|
95
|
+
force: true;
|
|
96
|
+
}) => Promise<void>;
|
|
97
|
+
writeFileFn?: (path: string, data: Buffer) => Promise<void>;
|
|
98
|
+
}) => Promise<RelocateServerAssetsResult>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import 'virtual/react-router/unstable_rsc/inject-hmr-runtime';
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import "virtual/react-router/unstable_rsc/inject-hmr-runtime";
|
|
2
|
+
import { hydrateRoot } from "react-dom/client";
|
|
3
|
+
import { unstable_RSCHydratedRouter, unstable_createCallServer, unstable_getRSCStream } from "react-router/dom";
|
|
4
|
+
import { createFromReadableStream, createTemporaryReferenceSet, encodeReply, setServerCallback } from "react-server-dom-rspack/client.browser";
|
|
5
|
+
import * as __rspack_external_react from "react";
|
|
6
|
+
let hydrationWindow = window, InitialRscDataLoadGuard = ({ active, children })=>(__rspack_external_react.useEffect(()=>{
|
|
7
|
+
let frame;
|
|
8
|
+
if (!active) return;
|
|
9
|
+
let clearGuardOnceDataLoadStarts = ()=>{
|
|
10
|
+
let router = hydrationWindow.__reactRouterDataRouter;
|
|
11
|
+
if (router && (router.state.initialized || 'idle' !== router.state.navigation.state)) {
|
|
12
|
+
hydrationWindow.__reactRouterHdrActive = !1;
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
frame = requestAnimationFrame(clearGuardOnceDataLoadStarts);
|
|
16
|
+
};
|
|
17
|
+
return frame = requestAnimationFrame(clearGuardOnceDataLoadStarts), ()=>cancelAnimationFrame(frame);
|
|
18
|
+
}, [
|
|
19
|
+
active
|
|
20
|
+
]), children);
|
|
21
|
+
setServerCallback(unstable_createCallServer({
|
|
22
|
+
createFromReadableStream: createFromReadableStream,
|
|
23
|
+
createTemporaryReferenceSet: createTemporaryReferenceSet,
|
|
24
|
+
encodeReply: encodeReply
|
|
25
|
+
}));
|
|
26
|
+
let hydrate = ()=>{
|
|
27
|
+
createFromReadableStream(unstable_getRSCStream()).then((payload)=>{
|
|
28
|
+
(0, __rspack_external_react.startTransition)(async ()=>{
|
|
29
|
+
let formState = 'render' === payload.type ? await payload.formState : void 0, needsInitialDataLoadGuard = 'render' === payload.type && payload.matches.some((match)=>null != match.clientLoader && !match.hasLoader && null != match.hydrateFallbackElement);
|
|
30
|
+
needsInitialDataLoadGuard && (hydrationWindow.__reactRouterHdrActive = !0), hydrateRoot(document, __rspack_external_react.createElement(__rspack_external_react.StrictMode, null, __rspack_external_react.createElement(InitialRscDataLoadGuard, {
|
|
31
|
+
active: needsInitialDataLoadGuard
|
|
32
|
+
}, __rspack_external_react.createElement(unstable_RSCHydratedRouter, {
|
|
33
|
+
createFromReadableStream: createFromReadableStream,
|
|
34
|
+
payload
|
|
35
|
+
}))), {
|
|
36
|
+
formState
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
}, (error)=>{
|
|
40
|
+
setTimeout(()=>{
|
|
41
|
+
throw error;
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
};
|
|
45
|
+
'loading' === document.readyState ? document.addEventListener('DOMContentLoaded', hydrate, {
|
|
46
|
+
once: !0
|
|
47
|
+
}) : hydrate();
|
|
48
|
+
let hot = import.meta.webpackHot;
|
|
49
|
+
hot?.on('rsc:update', (data)=>{
|
|
50
|
+
requestAnimationFrame(()=>{
|
|
51
|
+
let router = window.__reactRouterDataRouter;
|
|
52
|
+
if (data?.revalidate) return void router?.revalidate();
|
|
53
|
+
if (router?.navigate) {
|
|
54
|
+
let basename = router.basename || '/', pathname = window.location.pathname;
|
|
55
|
+
'/' !== basename && pathname.startsWith(basename) && '/' !== (pathname = pathname.slice(basename.length) || '/')[0] && (pathname = '/' + pathname), router.navigate(pathname + window.location.search + window.location.hash, {
|
|
56
|
+
replace: !0,
|
|
57
|
+
preventScrollReset: !0
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { RouterContextProvider } from 'react-router';
|
|
2
|
+
import unstable_reactRouterServeConfig from 'virtual/react-router/unstable_rsc/react-router-serve-config';
|
|
3
|
+
export { unstable_reactRouterServeConfig };
|
|
4
|
+
type RscRequestHandler = {
|
|
5
|
+
fetch(request: Request, requestContext?: RouterContextProvider): Promise<Response>;
|
|
6
|
+
};
|
|
7
|
+
export declare function fetchServer(request: Request, requestContext?: RouterContextProvider): Promise<Response>;
|
|
8
|
+
declare const handler: RscRequestHandler;
|
|
9
|
+
export default handler;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { createTemporaryReferenceSet, decodeAction, decodeFormState, decodeReply, loadServerAction, renderToReadableStream } from "react-server-dom-rspack/server.node";
|
|
2
|
+
import { RouterContextProvider, unstable_matchRSCServerRequest } from "react-router";
|
|
3
|
+
import routes from "virtual/react-router/unstable_rsc/routes";
|
|
4
|
+
import route_discovery from "virtual/react-router/unstable_rsc/route-discovery";
|
|
5
|
+
import basename from "virtual/react-router/unstable_rsc/basename";
|
|
6
|
+
import allowed_action_origins from "virtual/react-router/unstable_rsc/allowed-action-origins";
|
|
7
|
+
import client_version from "virtual/react-router/unstable_rsc/client-version";
|
|
8
|
+
import server_manifest from "virtual/react-router/unstable_rsc/server-manifest";
|
|
9
|
+
import bootstrap_scripts from "virtual/react-router/unstable_rsc/bootstrap-scripts";
|
|
10
|
+
import { generateHTML } from "./entry.rsc.ssr.js";
|
|
11
|
+
function fetchServer(request, requestContext) {
|
|
12
|
+
return unstable_matchRSCServerRequest({
|
|
13
|
+
allowedActionOrigins: allowed_action_origins,
|
|
14
|
+
basename: basename,
|
|
15
|
+
clientVersion: client_version,
|
|
16
|
+
createTemporaryReferenceSet: createTemporaryReferenceSet,
|
|
17
|
+
decodeAction: (body)=>decodeAction(body, server_manifest()),
|
|
18
|
+
decodeFormState: async (actionResult, body)=>await decodeFormState(actionResult, body, server_manifest()) ?? void 0,
|
|
19
|
+
decodeReply: decodeReply,
|
|
20
|
+
loadServerAction: (id)=>Promise.resolve(loadServerAction(id)),
|
|
21
|
+
request,
|
|
22
|
+
requestContext,
|
|
23
|
+
routes: routes,
|
|
24
|
+
routeDiscovery: route_discovery,
|
|
25
|
+
generateResponse: (match, options)=>new Response(renderToReadableStream(match.payload, options), {
|
|
26
|
+
status: match.statusCode,
|
|
27
|
+
headers: match.headers
|
|
28
|
+
})
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
import.meta.webpackHot?.accept();
|
|
32
|
+
export { default as unstable_reactRouterServeConfig } from "virtual/react-router/unstable_rsc/react-router-serve-config";
|
|
33
|
+
export default {
|
|
34
|
+
fetch: async (request, requestContext)=>(!requestContext || requestContext instanceof RouterContextProvider || (requestContext = void 0), generateHTML(request, await fetchServer(request, requestContext), {
|
|
35
|
+
bootstrapScripts: bootstrap_scripts
|
|
36
|
+
}))
|
|
37
|
+
};
|
|
38
|
+
export { fetchServer };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { renderToReadableStream } from "react-dom/server";
|
|
2
|
+
import { unstable_RSCStaticRouter, unstable_routeRSCServerRequest } from "react-router";
|
|
3
|
+
import { createFromReadableStream } from "react-server-dom-rspack/client.node";
|
|
4
|
+
import * as __rspack_external_react from "react";
|
|
5
|
+
async function generateHTML(request, serverResponse, options = {}) {
|
|
6
|
+
return unstable_routeRSCServerRequest({
|
|
7
|
+
request,
|
|
8
|
+
serverResponse,
|
|
9
|
+
createFromReadableStream: createFromReadableStream,
|
|
10
|
+
async renderHTML (getPayload, renderOptions) {
|
|
11
|
+
let payloadPromise = getPayload();
|
|
12
|
+
return payloadPromise.formState ??= payloadPromise.then((payload)=>'render' === payload.type ? payload.formState : void 0), renderToReadableStream(__rspack_external_react.createElement(unstable_RSCStaticRouter, {
|
|
13
|
+
getPayload: getPayload
|
|
14
|
+
}), {
|
|
15
|
+
...renderOptions,
|
|
16
|
+
bootstrapModules: options.bootstrapModules,
|
|
17
|
+
bootstrapScripts: options.bootstrapScripts,
|
|
18
|
+
formState: await payloadPromise.formState,
|
|
19
|
+
signal: request.signal
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
export { generateHTML };
|
package/dist/typegen.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { RsbuildPluginAPI } from '@rsbuild/core';
|
|
2
|
+
import { type PluginEffectRuntime } from './effect-runtime.js';
|
|
2
3
|
type Execa = typeof import('execa').execa;
|
|
3
4
|
type LoadExeca = () => Promise<Execa>;
|
|
4
5
|
export type ReactRouterTypegenRunner = {
|
|
@@ -7,9 +8,10 @@ export type ReactRouterTypegenRunner = {
|
|
|
7
8
|
runBuild(): Promise<void>;
|
|
8
9
|
};
|
|
9
10
|
export declare const createReactRouterTypegenRunner: (loadExeca?: LoadExeca, appDirectory?: string) => ReactRouterTypegenRunner;
|
|
10
|
-
export declare const registerReactRouterTypegen: (api: RsbuildPluginAPI, { runner, devWatchDelayMs, appDirectory, }
|
|
11
|
+
export declare const registerReactRouterTypegen: (api: RsbuildPluginAPI, { runtime, runner, devWatchDelayMs, appDirectory, }: {
|
|
12
|
+
runtime: PluginEffectRuntime;
|
|
11
13
|
runner?: ReactRouterTypegenRunner;
|
|
12
14
|
devWatchDelayMs?: number;
|
|
13
15
|
appDirectory?: string;
|
|
14
|
-
}) => void
|
|
16
|
+
}) => Promise<void>;
|
|
15
17
|
export {};
|
package/dist/types.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { RsbuildConfig } from '@rsbuild/core';
|
|
1
|
+
import type { RsbuildConfig, Rspack } from '@rsbuild/core';
|
|
2
2
|
export type Route = {
|
|
3
3
|
id: string;
|
|
4
4
|
parentId?: string;
|
|
@@ -25,6 +25,20 @@ export type PluginOptions = {
|
|
|
25
25
|
* Federation mode configuration
|
|
26
26
|
*/
|
|
27
27
|
federation?: boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Enable experimental React Router RSC framework mode.
|
|
30
|
+
* This composes `rsbuild-plugin-rsc` with React Router's Rsbuild
|
|
31
|
+
* environments. Environment names are managed by this plugin.
|
|
32
|
+
* Requires `react-router >=7.18.0 || >=8.0.0`, `rsbuild-plugin-rsc`,
|
|
33
|
+
* and `react-server-dom-rspack`.
|
|
34
|
+
* @default false
|
|
35
|
+
*/
|
|
36
|
+
rsc?: boolean | {
|
|
37
|
+
layers?: {
|
|
38
|
+
rsc?: Rspack.RuleSetCondition;
|
|
39
|
+
ssr?: Rspack.RuleSetCondition;
|
|
40
|
+
};
|
|
41
|
+
};
|
|
28
42
|
/**
|
|
29
43
|
* Rsbuild dev-only lazy compilation behavior.
|
|
30
44
|
*
|
|
@@ -63,6 +77,21 @@ export type PluginOptions = {
|
|
|
63
77
|
*/
|
|
64
78
|
onRouteTopologyChange?: () => void | Promise<void>;
|
|
65
79
|
};
|
|
80
|
+
export type ReactRouterRSCPluginOptions = Omit<PluginOptions, 'rsc'> & {
|
|
81
|
+
/**
|
|
82
|
+
* Optional overrides forwarded to `rsbuild-plugin-rsc`.
|
|
83
|
+
* Environment names are managed by this plugin.
|
|
84
|
+
*/
|
|
85
|
+
rsc?: Exclude<NonNullable<PluginOptions['rsc']>, boolean>;
|
|
86
|
+
};
|
|
87
|
+
export type PrerenderPathsConfig = boolean | string[] | ((args: {
|
|
88
|
+
getStaticPaths: () => string[];
|
|
89
|
+
}) => boolean | string[] | Promise<boolean | string[]>);
|
|
90
|
+
export type PrerenderConfigObject = {
|
|
91
|
+
paths: PrerenderPathsConfig;
|
|
92
|
+
concurrency?: number;
|
|
93
|
+
unstable_concurrency?: number;
|
|
94
|
+
};
|
|
66
95
|
export type RouteManifestItem = Omit<Route, 'file' | 'children'> & {
|
|
67
96
|
module: string;
|
|
68
97
|
clientActionModule?: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rsbuild-plugin-react-router",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "React Router plugin for Rsbuild",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -37,6 +37,18 @@
|
|
|
37
37
|
"types": "./dist/templates/entry.server.d.ts",
|
|
38
38
|
"import": "./dist/templates/entry.server.js",
|
|
39
39
|
"require": "./dist/templates/entry.server.cjs"
|
|
40
|
+
},
|
|
41
|
+
"./templates/entry.rsc": {
|
|
42
|
+
"types": "./dist/templates/entry.rsc.d.ts",
|
|
43
|
+
"import": "./dist/templates/entry.rsc.js"
|
|
44
|
+
},
|
|
45
|
+
"./templates/entry.rsc.client": {
|
|
46
|
+
"types": "./dist/templates/entry.rsc.client.d.ts",
|
|
47
|
+
"import": "./dist/templates/entry.rsc.client.js"
|
|
48
|
+
},
|
|
49
|
+
"./templates/entry.rsc.ssr": {
|
|
50
|
+
"types": "./dist/templates/entry.rsc.ssr.d.ts",
|
|
51
|
+
"import": "./dist/templates/entry.rsc.ssr.js"
|
|
40
52
|
}
|
|
41
53
|
},
|
|
42
54
|
"main": "./dist/index.cjs",
|
|
@@ -50,8 +62,8 @@
|
|
|
50
62
|
},
|
|
51
63
|
"dependencies": {
|
|
52
64
|
"@jridgewell/remapping": "^2.3.5",
|
|
53
|
-
"@react-router/node": "^7.13.0",
|
|
54
|
-
"@remix-run/node-fetch-server": "^0.13.
|
|
65
|
+
"@react-router/node": "^7.13.0 || ^8.0.0",
|
|
66
|
+
"@remix-run/node-fetch-server": "^0.13.3",
|
|
55
67
|
"@rspack/plugin-react-refresh": "^2.0.2",
|
|
56
68
|
"execa": "^9.6.1",
|
|
57
69
|
"fs-extra": "11.3.3",
|
|
@@ -68,40 +80,76 @@
|
|
|
68
80
|
"@changesets/cli": "^2.29.8",
|
|
69
81
|
"@codspeed/vitest-plugin": "^5.7.1",
|
|
70
82
|
"@jridgewell/trace-mapping": "^0.3.31",
|
|
83
|
+
"@playwright/test": "^1.61.1",
|
|
71
84
|
"@react-router/dev": "^8.0.1",
|
|
72
|
-
"@
|
|
85
|
+
"@react-router/express": "^8.0.1",
|
|
86
|
+
"@react-router/fs-routes": "^8.0.1",
|
|
87
|
+
"@react-router/remix-routes-option-adapter": "^8.0.1",
|
|
88
|
+
"@react-router/serve": "^8.0.1",
|
|
89
|
+
"@rsbuild/core": "2.2.0",
|
|
90
|
+
"@rsbuild/plugin-less": "1.6.4",
|
|
91
|
+
"@rsbuild/plugin-mdx": "^1.1.3",
|
|
73
92
|
"@rsbuild/plugin-react": "2.1.0",
|
|
93
|
+
"@rsbuild/plugin-sass": "1.5.3",
|
|
94
|
+
"@rsbuild/plugin-svgr": "2.0.4",
|
|
95
|
+
"@rsbuild/plugin-tailwindcss": "2.0.3",
|
|
74
96
|
"@rslib/core": "^0.23.2",
|
|
75
|
-
"@rspack/core": "2.
|
|
76
|
-
"@rstest/core": "^0.11.
|
|
77
|
-
"@rstest/coverage-istanbul": "^0.11.
|
|
97
|
+
"@rspack/core": "2.2.0",
|
|
98
|
+
"@rstest/core": "^0.11.4",
|
|
99
|
+
"@rstest/coverage-istanbul": "^0.11.4",
|
|
78
100
|
"@swc/helpers": "^0.5.23",
|
|
79
101
|
"@types/fs-extra": "11.0.4",
|
|
80
102
|
"@types/jsesc": "^3.0.3",
|
|
81
103
|
"@types/node": "^25.0.10",
|
|
82
104
|
"@types/react": "^19.2.10",
|
|
83
105
|
"@types/react-dom": "^19.2.3",
|
|
84
|
-
"
|
|
106
|
+
"@types/webpack-env": "^1.18.8",
|
|
107
|
+
"@vanilla-extract/css": "^1.20.1",
|
|
108
|
+
"cheerio": "^1.2.0",
|
|
109
|
+
"cross-spawn": "^7.0.6",
|
|
110
|
+
"dedent": "^1.7.2",
|
|
111
|
+
"effect": "^3.22.0",
|
|
85
112
|
"es-module-lexer": "1.7.0",
|
|
113
|
+
"express": "^4.22.2",
|
|
114
|
+
"fast-glob": "^3.3.3",
|
|
115
|
+
"get-port": "7.1.0",
|
|
86
116
|
"kill-port": "^2.0.1",
|
|
87
117
|
"pkg-pr-new": "^0.0.75",
|
|
88
118
|
"playwright": "^1.61.1",
|
|
89
119
|
"prettier": "3.8.1",
|
|
90
120
|
"react": "^19.2.4",
|
|
91
121
|
"react-dom": "^19.2.4",
|
|
92
|
-
"react-router": "^7.
|
|
93
|
-
"react-router-dom": "^7.
|
|
122
|
+
"react-router": "^7.18.0",
|
|
123
|
+
"react-router-dom": "^7.18.0",
|
|
124
|
+
"react-server-dom-rspack": "0.1.0",
|
|
125
|
+
"rsbuild-plugin-rsc": "^0.1.1",
|
|
126
|
+
"semver": "^7.8.5",
|
|
127
|
+
"shelljs": "^0.10.0",
|
|
128
|
+
"strip-ansi": "^7.2.0",
|
|
129
|
+
"strip-indent": "^4.1.1",
|
|
130
|
+
"tailwindcss": "4.3.2",
|
|
131
|
+
"type-fest": "^5.7.0",
|
|
94
132
|
"typescript": "^5.9.3",
|
|
95
133
|
"vitest": "^4.1.10",
|
|
134
|
+
"wait-on": "^9.0.10",
|
|
96
135
|
"@rsbuild/config": "1.0.1"
|
|
97
136
|
},
|
|
98
137
|
"peerDependencies": {
|
|
99
138
|
"@react-router/dev": "^7.13.0 || ^8.0.0",
|
|
100
|
-
"@rsbuild/core": "^2.
|
|
139
|
+
"@rsbuild/core": "^2.2.0",
|
|
140
|
+
"react-router": "^7.13.0 || ^8.0.0",
|
|
141
|
+
"react-server-dom-rspack": "0.1.0",
|
|
142
|
+
"rsbuild-plugin-rsc": "^0.1.1"
|
|
101
143
|
},
|
|
102
144
|
"peerDependenciesMeta": {
|
|
103
145
|
"@react-router/dev": {
|
|
104
146
|
"optional": true
|
|
147
|
+
},
|
|
148
|
+
"react-server-dom-rspack": {
|
|
149
|
+
"optional": true
|
|
150
|
+
},
|
|
151
|
+
"rsbuild-plugin-rsc": {
|
|
152
|
+
"optional": true
|
|
105
153
|
}
|
|
106
154
|
},
|
|
107
155
|
"publishConfig": {
|
|
@@ -113,15 +161,22 @@
|
|
|
113
161
|
"build": "rslib build",
|
|
114
162
|
"bench": "pnpm build && node benchmarks/run.mts",
|
|
115
163
|
"bench:smoke": "pnpm build && node benchmarks/run.mts --iterations 1 --warmup 0",
|
|
116
|
-
"bench:codspeed": "pnpm build && vitest bench --run --config vitest.benchmark.config.mts",
|
|
117
|
-
"e2e": "pnpm build && pnpm
|
|
164
|
+
"bench:codspeed": "pnpm build && vitest bench --run --config vitest.benchmark.config.mts -t build-256-ssr",
|
|
165
|
+
"e2e": "pnpm build && pnpm e2e:no-build",
|
|
166
|
+
"e2e:no-build": "pnpm test:package-interop && pnpm --filter './examples/{default-template,spa-mode,prerender,custom-node-server,cloudflare,client-only,react-router-8,rsc-mode}' test:e2e",
|
|
118
167
|
"dev": "rslib build --watch",
|
|
119
|
-
"test": "rstest run",
|
|
168
|
+
"test": "pnpm typecheck && rstest run",
|
|
169
|
+
"typecheck": "tsc --noEmit && tsc -p tsconfig.tests.json && pnpm --filter integration typecheck && pnpm --filter integration-rsbuild-template typecheck && pnpm --filter integration-rsc-framework typecheck && pnpm --filter integration-rsc-preview typecheck",
|
|
120
170
|
"test:watch": "rstest watch",
|
|
121
171
|
"test:coverage": "rstest run --coverage",
|
|
122
172
|
"test:core": "rstest run -c ./rstest.config.ts",
|
|
123
173
|
"test:core:watch": "rstest watch -c ./rstest.config.ts",
|
|
124
174
|
"test:package-interop": "node scripts/test-package-interop.mts",
|
|
175
|
+
"test:react-router-framework": "pnpm build && playwright test --config tests/react-router-framework/integration/playwright.config.ts",
|
|
176
|
+
"test:react-router-framework:failfast": "pnpm build && pnpm test:react-router-framework:failfast:no-build",
|
|
177
|
+
"test:react-router-framework:failfast:no-build": "RR_FRAMEWORK_MAX_WORKERS=2 playwright test --config tests/react-router-framework/integration/playwright.config.ts tests/react-router-framework/integration/hmr-hdr-test.ts --workers=2 --max-failures=1 --retries=0 --reporter=line && RR_FRAMEWORK_MAX_WORKERS=2 playwright test --config tests/react-router-framework/integration/playwright.config.ts tests/react-router-framework/integration/hmr-hdr-rsc-test.ts --workers=2 --max-failures=1 --retries=0 --reporter=line && RR_FRAMEWORK_MAX_WORKERS=4 playwright test --config tests/react-router-framework/integration/playwright.config.ts --grep-invert 'HMR & HDR' --workers=4 --max-failures=1 --retries=0 --reporter=line",
|
|
178
|
+
"test:react-router-framework:smoke": "pnpm build && playwright test --config tests/react-router-framework/integration/playwright.config.ts use-route-test.ts loader-test.ts",
|
|
179
|
+
"check:react-router-framework-upstream": "node scripts/check-react-router-framework-upstream.mjs",
|
|
125
180
|
"format": "prettier --write \"src/**/*.{js,jsx,ts,tsx}\"",
|
|
126
181
|
"format:check": "prettier --check \"src/**/*.{js,jsx,ts,tsx}\"",
|
|
127
182
|
"changeset": "changeset",
|