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
|
@@ -3,19 +3,77 @@ import jsesc from 'jsesc';
|
|
|
3
3
|
import { relative } from 'pathe';
|
|
4
4
|
import { PLUGIN_NAME } from './constants.js';
|
|
5
5
|
import {
|
|
6
|
+
createReactRouterManifestOptions,
|
|
6
7
|
getReactRouterManifestForDev,
|
|
8
|
+
type ReactRouterManifestForDev as ReactRouterManifest,
|
|
9
|
+
type RouteChunkManifestOptions,
|
|
10
|
+
type RouteModuleAnalysisProvider,
|
|
7
11
|
type ReactRouterManifestStats,
|
|
8
12
|
} from './manifest.js';
|
|
9
13
|
import type { ReactRouterPerformanceProfiler } from './performance.js';
|
|
14
|
+
import {
|
|
15
|
+
validateSpaModeRouteExports,
|
|
16
|
+
type RouteTransformRunner,
|
|
17
|
+
} from './route-transform-tasks.js';
|
|
10
18
|
import { createBundlerRouteExportResolver } from './route-export-resolution.js';
|
|
11
|
-
import
|
|
12
|
-
|
|
19
|
+
import {
|
|
20
|
+
getRouteChunkNameFromModuleId,
|
|
21
|
+
type RouteChunkConfig,
|
|
22
|
+
} from './route-chunks.js';
|
|
13
23
|
import type { PluginOptions, Route } from './types.js';
|
|
14
24
|
import { isSourceMapEnabled } from './warnings/warn-on-client-source-maps.js';
|
|
25
|
+
import {
|
|
26
|
+
analyzeRouteModuleCode,
|
|
27
|
+
type RouteModuleAnalysis,
|
|
28
|
+
} from './export-utils.js';
|
|
29
|
+
import {
|
|
30
|
+
relocateServerAssetsToClient,
|
|
31
|
+
type RelocatableAssetCompilation,
|
|
32
|
+
} from './ssr-asset-relocation.js';
|
|
15
33
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
34
|
+
/**
|
|
35
|
+
* Register the node-compilation hook that relocates server-only static assets
|
|
36
|
+
* (`?url` imports, `.css?url` files, and other `asset/resource` outputs
|
|
37
|
+
* referenced only by loaders or `.server` modules) into the client build. The
|
|
38
|
+
* loader/`links()` export returns the asset URL to the client, which fetches it
|
|
39
|
+
* from `build/client` at runtime, so the file must exist there even though only
|
|
40
|
+
* the node compilation referenced it. The assets are also stripped from the
|
|
41
|
+
* server build to avoid shipping duplicate static files, mirroring upstream
|
|
42
|
+
* React Router's Vite plugin. This runs for every node compilation, so it also
|
|
43
|
+
* covers `serverBundles` (multiple node outputs) and dev mode (where
|
|
44
|
+
* `writeToDisk` is enabled).
|
|
45
|
+
*
|
|
46
|
+
* Registered by both the classic build-output transforms and the RSC branch so
|
|
47
|
+
* `.css?url`/`?url` assets referenced from `links()` resolve in RSC framework
|
|
48
|
+
* mode too.
|
|
49
|
+
*/
|
|
50
|
+
export const registerSsrAssetRelocation = ({
|
|
51
|
+
api,
|
|
52
|
+
outputClientPath,
|
|
53
|
+
performanceProfiler,
|
|
54
|
+
}: {
|
|
55
|
+
api: RsbuildPluginAPI;
|
|
56
|
+
outputClientPath: string;
|
|
57
|
+
performanceProfiler: ReactRouterPerformanceProfiler;
|
|
58
|
+
}): void => {
|
|
59
|
+
const relocatedDestinations = new Map<string, string>();
|
|
60
|
+
api.processAssets(
|
|
61
|
+
{ stage: 'report', targets: ['node'] },
|
|
62
|
+
async ({ compilation }) => {
|
|
63
|
+
await performanceProfiler.record(
|
|
64
|
+
'node',
|
|
65
|
+
'assets:relocate-ssr-only',
|
|
66
|
+
'ssr-only-assets',
|
|
67
|
+
() =>
|
|
68
|
+
relocateServerAssetsToClient({
|
|
69
|
+
compilation: compilation as unknown as RelocatableAssetCompilation,
|
|
70
|
+
outputClientPath,
|
|
71
|
+
relocatedDestinations,
|
|
72
|
+
})
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
);
|
|
76
|
+
};
|
|
19
77
|
|
|
20
78
|
type RegisterBuildOutputTransformsOptions = {
|
|
21
79
|
api: RsbuildPluginAPI;
|
|
@@ -30,7 +88,8 @@ type RegisterBuildOutputTransformsOptions = {
|
|
|
30
88
|
getClientStats: () => ReactRouterManifestStats | undefined;
|
|
31
89
|
appDirectory: string;
|
|
32
90
|
getAssetPrefix: () => string;
|
|
33
|
-
routeChunkOptions:
|
|
91
|
+
routeChunkOptions: RouteChunkManifestOptions | undefined;
|
|
92
|
+
routeModuleAnalysis?: RouteModuleAnalysisProvider;
|
|
34
93
|
routeTransformRunner: RouteTransformRunner;
|
|
35
94
|
routeByFilePath: Map<string, Route>;
|
|
36
95
|
routeChunkConfig: RouteChunkConfig;
|
|
@@ -40,7 +99,12 @@ type RegisterBuildOutputTransformsOptions = {
|
|
|
40
99
|
ssr: boolean;
|
|
41
100
|
isSpaMode: boolean;
|
|
42
101
|
rootRoutePath: string;
|
|
102
|
+
outputClientPath: string;
|
|
43
103
|
isDevHmrEnabled?: () => boolean;
|
|
104
|
+
onRouteModuleAnalysis?: (
|
|
105
|
+
resourcePath: string,
|
|
106
|
+
analysis: RouteModuleAnalysis
|
|
107
|
+
) => void;
|
|
44
108
|
};
|
|
45
109
|
|
|
46
110
|
export const registerBuildOutputTransforms = ({
|
|
@@ -55,6 +119,7 @@ export const registerBuildOutputTransforms = ({
|
|
|
55
119
|
appDirectory,
|
|
56
120
|
getAssetPrefix,
|
|
57
121
|
routeChunkOptions,
|
|
122
|
+
routeModuleAnalysis,
|
|
58
123
|
routeTransformRunner,
|
|
59
124
|
routeByFilePath,
|
|
60
125
|
routeChunkConfig,
|
|
@@ -64,10 +129,26 @@ export const registerBuildOutputTransforms = ({
|
|
|
64
129
|
ssr,
|
|
65
130
|
isSpaMode,
|
|
66
131
|
rootRoutePath,
|
|
132
|
+
outputClientPath,
|
|
67
133
|
isDevHmrEnabled = () => false,
|
|
134
|
+
onRouteModuleAnalysis,
|
|
68
135
|
}: RegisterBuildOutputTransformsOptions): void => {
|
|
69
|
-
const
|
|
70
|
-
|
|
136
|
+
const rememberRouteModuleAnalysis = (
|
|
137
|
+
args: Parameters<TransformHandler>[0]
|
|
138
|
+
): void => {
|
|
139
|
+
if (!routeByFilePath.has(args.resourcePath)) {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
onRouteModuleAnalysis?.(
|
|
143
|
+
args.resourcePath,
|
|
144
|
+
analyzeRouteModuleCode(args.code)
|
|
145
|
+
);
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
const transformRouteModule = async (
|
|
149
|
+
args: Parameters<TransformHandler>[0]
|
|
150
|
+
) => {
|
|
151
|
+
return performanceProfiler.record(
|
|
71
152
|
args.environment?.name,
|
|
72
153
|
'route:module',
|
|
73
154
|
args.resource,
|
|
@@ -88,6 +169,7 @@ export const registerBuildOutputTransforms = ({
|
|
|
88
169
|
devHmr: isDevHmrEnabled(),
|
|
89
170
|
})
|
|
90
171
|
);
|
|
172
|
+
};
|
|
91
173
|
|
|
92
174
|
api.processAssets(
|
|
93
175
|
{ stage: 'additional', targets: ['node'] },
|
|
@@ -105,6 +187,8 @@ export const registerBuildOutputTransforms = ({
|
|
|
105
187
|
}
|
|
106
188
|
);
|
|
107
189
|
|
|
190
|
+
registerSsrAssetRelocation({ api, outputClientPath, performanceProfiler });
|
|
191
|
+
|
|
108
192
|
api.transform(
|
|
109
193
|
{
|
|
110
194
|
test: /virtual\/react-router\/(browser|server)-manifest/,
|
|
@@ -137,7 +221,10 @@ export const registerBuildOutputTransforms = ({
|
|
|
137
221
|
getClientStats(),
|
|
138
222
|
appDirectory,
|
|
139
223
|
getAssetPrefix(),
|
|
140
|
-
|
|
224
|
+
createReactRouterManifestOptions({
|
|
225
|
+
routeChunks: routeChunkOptions,
|
|
226
|
+
routeModuleAnalysis,
|
|
227
|
+
})
|
|
141
228
|
));
|
|
142
229
|
return {
|
|
143
230
|
code: `export default ${jsesc(manifest, { es6: true })};`,
|
|
@@ -149,9 +236,11 @@ export const registerBuildOutputTransforms = ({
|
|
|
149
236
|
api.transform(
|
|
150
237
|
{
|
|
151
238
|
resourceQuery: /__react-router-build-client-route/,
|
|
239
|
+
order: 'post',
|
|
152
240
|
},
|
|
153
|
-
async args =>
|
|
154
|
-
|
|
241
|
+
async args => {
|
|
242
|
+
rememberRouteModuleAnalysis(args);
|
|
243
|
+
return performanceProfiler.record(
|
|
155
244
|
args.environment?.name,
|
|
156
245
|
'route:client-entry',
|
|
157
246
|
args.resource,
|
|
@@ -166,29 +255,67 @@ export const registerBuildOutputTransforms = ({
|
|
|
166
255
|
routeId: routeByFilePath.get(args.resourcePath)?.id,
|
|
167
256
|
devHmr: isDevHmrEnabled(),
|
|
168
257
|
})
|
|
169
|
-
)
|
|
258
|
+
);
|
|
259
|
+
}
|
|
170
260
|
);
|
|
171
261
|
|
|
172
262
|
api.transform(
|
|
173
263
|
{
|
|
174
264
|
resourceQuery: /route-chunk=/,
|
|
175
265
|
environments: ['web'],
|
|
266
|
+
order: 'post',
|
|
176
267
|
},
|
|
177
|
-
async args =>
|
|
178
|
-
performanceProfiler.record(
|
|
268
|
+
async args => {
|
|
269
|
+
return performanceProfiler.record(
|
|
179
270
|
args.environment?.name,
|
|
180
271
|
'route:chunk',
|
|
181
272
|
args.resource,
|
|
182
|
-
async () =>
|
|
183
|
-
|
|
273
|
+
async () => {
|
|
274
|
+
const routeChunkName = getRouteChunkNameFromModuleId(args.resource);
|
|
275
|
+
if (isBuild && isSpaMode && routeChunkName === 'main') {
|
|
276
|
+
validateSpaModeRouteExports({
|
|
277
|
+
exportNames: analyzeRouteModuleCode(args.code, args.resourcePath)
|
|
278
|
+
.exports,
|
|
279
|
+
resourcePath: args.resourcePath,
|
|
280
|
+
rootRoutePath,
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
const routeChunkArtifact = await routeTransformRunner({
|
|
184
285
|
kind: 'routeChunk',
|
|
185
286
|
code: args.code,
|
|
186
287
|
resource: args.resource,
|
|
187
288
|
resourcePath: args.resourcePath,
|
|
188
289
|
isBuild,
|
|
189
290
|
routeChunkConfig,
|
|
190
|
-
})
|
|
191
|
-
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
// Invariant with the transformRouteModule registration below: in
|
|
294
|
+
// split-chunk production builds, web route modules are transformed
|
|
295
|
+
// HERE (on the main chunk) and the shared registration is scoped to
|
|
296
|
+
// ['node']. If either gate changes, web modules get transformed
|
|
297
|
+
// twice or not at all.
|
|
298
|
+
if (!isBuild || routeChunkName !== 'main') {
|
|
299
|
+
return routeChunkArtifact;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
return routeTransformRunner({
|
|
303
|
+
kind: 'routeModule',
|
|
304
|
+
code: routeChunkArtifact.code,
|
|
305
|
+
resource: args.resource,
|
|
306
|
+
resourcePath: args.resourcePath,
|
|
307
|
+
environmentName: 'web',
|
|
308
|
+
sourceMaps: isSourceMapEnabled(
|
|
309
|
+
args.environment.config.output.sourceMap
|
|
310
|
+
),
|
|
311
|
+
ssr,
|
|
312
|
+
isBuild,
|
|
313
|
+
isSpaMode,
|
|
314
|
+
rootRoutePath,
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
);
|
|
318
|
+
}
|
|
192
319
|
);
|
|
193
320
|
|
|
194
321
|
if (isBuild && splitRouteModules) {
|
|
@@ -199,9 +326,10 @@ export const registerBuildOutputTransforms = ({
|
|
|
199
326
|
not: /__react-router-build-client-route|react-router-route|route-chunk=/,
|
|
200
327
|
},
|
|
201
328
|
environments: ['web'],
|
|
329
|
+
order: 'post',
|
|
202
330
|
},
|
|
203
|
-
async args =>
|
|
204
|
-
performanceProfiler.record(
|
|
331
|
+
async args => {
|
|
332
|
+
return performanceProfiler.record(
|
|
205
333
|
args.environment?.name,
|
|
206
334
|
'route:split-exports',
|
|
207
335
|
args.resource,
|
|
@@ -212,7 +340,8 @@ export const registerBuildOutputTransforms = ({
|
|
|
212
340
|
resourcePath: args.resourcePath,
|
|
213
341
|
routeChunkConfig,
|
|
214
342
|
})
|
|
215
|
-
)
|
|
343
|
+
);
|
|
344
|
+
}
|
|
216
345
|
);
|
|
217
346
|
}
|
|
218
347
|
|
|
@@ -274,6 +403,11 @@ export const registerBuildOutputTransforms = ({
|
|
|
274
403
|
resourceQuery: {
|
|
275
404
|
not: /__react-router-build-client-route|react-router-route|route-chunk=/,
|
|
276
405
|
},
|
|
406
|
+
// Invariant with the route-chunk= handler above: when split-chunk
|
|
407
|
+
// production builds transform web modules on the main chunk, this
|
|
408
|
+
// registration must stay scoped to ['node'] so web modules are not
|
|
409
|
+
// transformed twice.
|
|
410
|
+
environments: isBuild && splitRouteModules ? ['node'] : undefined,
|
|
277
411
|
order: 'post',
|
|
278
412
|
},
|
|
279
413
|
transformRouteModule
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import type { RsbuildEntryDescription, RsbuildPluginAPI } from '@rsbuild/core';
|
|
3
|
+
import type { RouteConfigEntry } from '@react-router/dev/routes';
|
|
4
|
+
import { resolve } from 'pathe';
|
|
5
|
+
import {
|
|
6
|
+
getBuildManifest,
|
|
7
|
+
getRoutesByServerBundleId,
|
|
8
|
+
} from './build-manifest.js';
|
|
9
|
+
import { BUILD_CLIENT_ROUTE_QUERY_STRING } from './constants.js';
|
|
10
|
+
import {
|
|
11
|
+
DEV_HMR_RUNTIME_MODULE_ID,
|
|
12
|
+
type DevHmrPlanOptions,
|
|
13
|
+
} from './dev-hmr.js';
|
|
14
|
+
import {
|
|
15
|
+
createReactRouterDevRuntimeController,
|
|
16
|
+
type ReactRouterDevRuntimeController,
|
|
17
|
+
} from './dev-runtime-controller.js';
|
|
18
|
+
import { generateWithProps } from './plugin-utils.js';
|
|
19
|
+
import { resolvePrerenderPaths } from './prerender.js';
|
|
20
|
+
import { generateServerBuild } from './server-utils.js';
|
|
21
|
+
import {
|
|
22
|
+
createReactRouterServerBuildPlan,
|
|
23
|
+
type ReactRouterServerBundleEntry,
|
|
24
|
+
} from './server-build-plan.js';
|
|
25
|
+
import {
|
|
26
|
+
getRouteChunkEntryName,
|
|
27
|
+
getRouteChunkModuleId,
|
|
28
|
+
routeChunkExportNames,
|
|
29
|
+
} from './route-chunks.js';
|
|
30
|
+
import type { Config } from './react-router-config.js';
|
|
31
|
+
import type { Route } from './types.js';
|
|
32
|
+
|
|
33
|
+
type CreateClassicWebRouteEntriesOptions = {
|
|
34
|
+
appDirectory: string;
|
|
35
|
+
isBuild: boolean;
|
|
36
|
+
routes: Record<string, Route>;
|
|
37
|
+
splitRouteModules: boolean;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
type CreateClassicVirtualModulesOptions = {
|
|
41
|
+
allowedActionOrigins: string[] | undefined;
|
|
42
|
+
appDirectory: string;
|
|
43
|
+
assetsBuildDirectory: string;
|
|
44
|
+
basename: string;
|
|
45
|
+
devHmrRuntimeModule?: string;
|
|
46
|
+
entryServerPath: string;
|
|
47
|
+
future: Config['future'];
|
|
48
|
+
isSpaMode: boolean;
|
|
49
|
+
prerenderPaths: string[];
|
|
50
|
+
publicPath: string;
|
|
51
|
+
routeDiscovery: Config['routeDiscovery'];
|
|
52
|
+
routes: Record<string, Route>;
|
|
53
|
+
routesByServerBundleId: Record<string, Record<string, Route>>;
|
|
54
|
+
ssr: boolean;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
type CreateClassicBuildArtifactsOptions = {
|
|
58
|
+
api: RsbuildPluginAPI;
|
|
59
|
+
defaultEntryName: string;
|
|
60
|
+
isBuild: boolean;
|
|
61
|
+
prerenderConfig: Config['prerender'];
|
|
62
|
+
reactRouterConfig: Required<
|
|
63
|
+
Pick<
|
|
64
|
+
Config,
|
|
65
|
+
'appDirectory' | 'buildDirectory' | 'serverBuildFile' | 'future'
|
|
66
|
+
>
|
|
67
|
+
> &
|
|
68
|
+
Pick<Config, 'serverBundles'>;
|
|
69
|
+
routeConfig: RouteConfigEntry[];
|
|
70
|
+
routes: Record<string, Route>;
|
|
71
|
+
rootDirectory: string;
|
|
72
|
+
ssr: boolean;
|
|
73
|
+
devHmr?: DevHmrPlanOptions;
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
export type ClassicBuildArtifacts = {
|
|
77
|
+
buildManifest: Awaited<ReturnType<typeof getBuildManifest>>;
|
|
78
|
+
devRuntime: ReactRouterDevRuntimeController;
|
|
79
|
+
prerenderPaths: string[];
|
|
80
|
+
routesByServerBundleId: Record<string, Record<string, Route>>;
|
|
81
|
+
serverBundleEntries: ReactRouterServerBundleEntry[];
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
export const createClassicBuildArtifacts = async ({
|
|
85
|
+
api,
|
|
86
|
+
defaultEntryName,
|
|
87
|
+
isBuild,
|
|
88
|
+
prerenderConfig,
|
|
89
|
+
reactRouterConfig,
|
|
90
|
+
routeConfig,
|
|
91
|
+
routes,
|
|
92
|
+
rootDirectory,
|
|
93
|
+
ssr,
|
|
94
|
+
devHmr,
|
|
95
|
+
}: CreateClassicBuildArtifactsOptions): Promise<ClassicBuildArtifacts> => {
|
|
96
|
+
const buildManifest = await getBuildManifest({
|
|
97
|
+
reactRouterConfig,
|
|
98
|
+
routes,
|
|
99
|
+
rootDirectory,
|
|
100
|
+
});
|
|
101
|
+
const routesByServerBundleId = getRoutesByServerBundleId(
|
|
102
|
+
buildManifest,
|
|
103
|
+
routes
|
|
104
|
+
);
|
|
105
|
+
const serverBuildPlan = createReactRouterServerBuildPlan({
|
|
106
|
+
routesByServerBundleId,
|
|
107
|
+
serverBuildFile: reactRouterConfig.serverBuildFile,
|
|
108
|
+
defaultEntryName,
|
|
109
|
+
});
|
|
110
|
+
const prerenderPaths = await resolvePrerenderPaths(
|
|
111
|
+
prerenderConfig,
|
|
112
|
+
ssr,
|
|
113
|
+
routeConfig,
|
|
114
|
+
{
|
|
115
|
+
logWarning: true,
|
|
116
|
+
warn: message => api.logger.warn(message),
|
|
117
|
+
}
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
return {
|
|
121
|
+
buildManifest,
|
|
122
|
+
devRuntime: createReactRouterDevRuntimeController({
|
|
123
|
+
api,
|
|
124
|
+
isBuild,
|
|
125
|
+
buildPlan: serverBuildPlan,
|
|
126
|
+
clientPatchesRouteMetadata: devHmr?.isEnabled,
|
|
127
|
+
onNodeRebuildCommitted: devHmr?.onNodeRebuildCommitted,
|
|
128
|
+
}),
|
|
129
|
+
prerenderPaths,
|
|
130
|
+
routesByServerBundleId,
|
|
131
|
+
serverBundleEntries: serverBuildPlan.serverBundleEntries,
|
|
132
|
+
};
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
export const createClassicWebRouteEntries = ({
|
|
136
|
+
appDirectory,
|
|
137
|
+
isBuild,
|
|
138
|
+
routes,
|
|
139
|
+
splitRouteModules,
|
|
140
|
+
}: CreateClassicWebRouteEntriesOptions): {
|
|
141
|
+
manifestChunkNames: Set<string>;
|
|
142
|
+
webRouteEntries: Record<string, RsbuildEntryDescription>;
|
|
143
|
+
} => {
|
|
144
|
+
const manifestChunkNames = new Set<string>(['entry.client']);
|
|
145
|
+
const webRouteEntries = Object.values(routes).reduce(
|
|
146
|
+
(acc, route) => {
|
|
147
|
+
const entryName = route.file.slice(0, route.file.lastIndexOf('.'));
|
|
148
|
+
const routeFilePath = resolve(appDirectory, route.file);
|
|
149
|
+
manifestChunkNames.add(entryName);
|
|
150
|
+
acc[entryName] = {
|
|
151
|
+
import: `${routeFilePath}${BUILD_CLIENT_ROUTE_QUERY_STRING}`,
|
|
152
|
+
html: false,
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
if (isBuild && splitRouteModules && route.id !== 'root') {
|
|
156
|
+
let source: string;
|
|
157
|
+
try {
|
|
158
|
+
source = readFileSync(routeFilePath, 'utf8');
|
|
159
|
+
} catch (error) {
|
|
160
|
+
if ((error as NodeJS.ErrnoException).code === 'ENOENT') {
|
|
161
|
+
return acc;
|
|
162
|
+
}
|
|
163
|
+
throw error;
|
|
164
|
+
}
|
|
165
|
+
for (const exportName of routeChunkExportNames) {
|
|
166
|
+
if (!source.includes(exportName)) {
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
const chunkEntryName = getRouteChunkEntryName(route.id, exportName);
|
|
170
|
+
manifestChunkNames.add(chunkEntryName);
|
|
171
|
+
acc[chunkEntryName] = {
|
|
172
|
+
import: getRouteChunkModuleId(routeFilePath, exportName),
|
|
173
|
+
html: false,
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return acc;
|
|
179
|
+
},
|
|
180
|
+
{} as Record<string, RsbuildEntryDescription>
|
|
181
|
+
);
|
|
182
|
+
|
|
183
|
+
return {
|
|
184
|
+
manifestChunkNames,
|
|
185
|
+
webRouteEntries,
|
|
186
|
+
};
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
export const createClassicVirtualModules = ({
|
|
190
|
+
allowedActionOrigins,
|
|
191
|
+
appDirectory,
|
|
192
|
+
assetsBuildDirectory,
|
|
193
|
+
basename,
|
|
194
|
+
devHmrRuntimeModule,
|
|
195
|
+
entryServerPath,
|
|
196
|
+
future,
|
|
197
|
+
isSpaMode,
|
|
198
|
+
prerenderPaths,
|
|
199
|
+
publicPath,
|
|
200
|
+
routeDiscovery,
|
|
201
|
+
routes,
|
|
202
|
+
routesByServerBundleId,
|
|
203
|
+
ssr,
|
|
204
|
+
}: CreateClassicVirtualModulesOptions): Record<string, string> => {
|
|
205
|
+
const serverBuildOptions = {
|
|
206
|
+
entryServerPath,
|
|
207
|
+
assetsBuildDirectory,
|
|
208
|
+
basename,
|
|
209
|
+
appDirectory,
|
|
210
|
+
ssr,
|
|
211
|
+
isSpaMode,
|
|
212
|
+
future,
|
|
213
|
+
allowedActionOrigins,
|
|
214
|
+
prerender: prerenderPaths,
|
|
215
|
+
routeDiscovery,
|
|
216
|
+
publicPath,
|
|
217
|
+
};
|
|
218
|
+
const bundleVirtualModules = Object.fromEntries(
|
|
219
|
+
Object.entries(routesByServerBundleId).map(([bundleId, bundleRoutes]) => [
|
|
220
|
+
`virtual/react-router/server-build-${bundleId}`,
|
|
221
|
+
generateServerBuild(bundleRoutes, {
|
|
222
|
+
...serverBuildOptions,
|
|
223
|
+
serverManifestId: `virtual/react-router/server-manifest-${bundleId}`,
|
|
224
|
+
}),
|
|
225
|
+
])
|
|
226
|
+
);
|
|
227
|
+
const bundleManifestModules = Object.fromEntries(
|
|
228
|
+
Object.entries(routesByServerBundleId)
|
|
229
|
+
.filter(
|
|
230
|
+
([, bundleRoutes]) =>
|
|
231
|
+
bundleRoutes && Object.keys(bundleRoutes).length > 0
|
|
232
|
+
)
|
|
233
|
+
.map(([bundleId]) => [
|
|
234
|
+
`virtual/react-router/server-manifest-${bundleId}`,
|
|
235
|
+
'export default {};',
|
|
236
|
+
])
|
|
237
|
+
);
|
|
238
|
+
|
|
239
|
+
return {
|
|
240
|
+
'virtual/react-router/browser-manifest': 'export default {};',
|
|
241
|
+
'virtual/react-router/server-manifest': 'export default {};',
|
|
242
|
+
'virtual/react-router/server-build': generateServerBuild(
|
|
243
|
+
routes,
|
|
244
|
+
serverBuildOptions
|
|
245
|
+
),
|
|
246
|
+
...bundleVirtualModules,
|
|
247
|
+
...bundleManifestModules,
|
|
248
|
+
'virtual/react-router/with-props': generateWithProps(),
|
|
249
|
+
...(devHmrRuntimeModule !== undefined
|
|
250
|
+
? { [DEV_HMR_RUNTIME_MODULE_ID]: devHmrRuntimeModule }
|
|
251
|
+
: {}),
|
|
252
|
+
};
|
|
253
|
+
};
|