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.
Files changed (110) hide show
  1. package/README.md +58 -208
  2. package/dist/511.js +370 -331
  3. package/dist/build-output-transforms.d.ts +30 -6
  4. package/dist/classic-mode.d.ts +56 -0
  5. package/dist/config-imports.d.ts +8 -2
  6. package/dist/constants.d.ts +3 -0
  7. package/dist/dev-background-resources.d.ts +3 -1
  8. package/dist/dev-generation.d.ts +2 -3
  9. package/dist/dev-hmr.d.ts +8 -2
  10. package/dist/dev-runtime-controller.d.ts +6 -1
  11. package/dist/dev-source-maps.d.ts +4 -0
  12. package/dist/effect-runtime.d.ts +17 -5
  13. package/dist/entry-paths.d.ts +16 -0
  14. package/dist/environment-output.d.ts +6 -0
  15. package/dist/export-utils.d.ts +2 -1
  16. package/dist/index.cjs +3957 -2208
  17. package/dist/index.d.ts +3 -1
  18. package/dist/index.js +3470 -1793
  19. package/dist/lazy-compilation-prewarm.d.ts +8 -5
  20. package/dist/manifest.d.ts +16 -4
  21. package/dist/mode-plan.d.ts +82 -0
  22. package/dist/modify-browser-manifest.d.ts +8 -4
  23. package/dist/plugin-utils.d.ts +27 -1
  24. package/dist/prerender-build.d.ts +5 -5
  25. package/dist/prerender.d.ts +1 -5
  26. package/dist/react-router-config.d.ts +11 -3
  27. package/dist/route-artifacts.d.ts +4 -2
  28. package/dist/route-chunks.d.ts +2 -1
  29. package/dist/route-component-transform.d.ts +0 -2
  30. package/dist/route-export-pruning.d.ts +4 -1
  31. package/dist/route-imports.d.ts +18 -0
  32. package/dist/route-transform-tasks.d.ts +5 -0
  33. package/dist/route-watch.d.ts +11 -6
  34. package/dist/rsc-dev-server.d.ts +26 -0
  35. package/dist/rsc-prerender.d.ts +54 -0
  36. package/dist/rsc-route-config.d.ts +6 -0
  37. package/dist/rsc-route-exports.d.ts +15 -0
  38. package/dist/rsc-route-transform-loader.cjs +43 -0
  39. package/dist/rsc-route-transform-loader.d.ts +30 -0
  40. package/dist/rsc-route-transform-loader.js +16 -0
  41. package/dist/rsc-route-transform-registration.d.ts +12 -0
  42. package/dist/rsc-route-transforms.d.ts +21 -0
  43. package/dist/rsc-support.d.ts +23 -0
  44. package/dist/rsc-virtual-modules.d.ts +19 -0
  45. package/dist/server-build-plan.d.ts +2 -1
  46. package/dist/server-build-resolution.d.ts +1 -2
  47. package/dist/server-utils.d.ts +4 -5
  48. package/dist/ssr-asset-relocation.d.ts +98 -0
  49. package/dist/templates/entry.rsc.client.d.ts +1 -0
  50. package/dist/templates/entry.rsc.client.js +61 -0
  51. package/dist/templates/entry.rsc.d.ts +9 -0
  52. package/dist/templates/entry.rsc.js +38 -0
  53. package/dist/templates/entry.rsc.ssr.d.ts +4 -0
  54. package/dist/templates/entry.rsc.ssr.js +24 -0
  55. package/dist/typegen.d.ts +4 -2
  56. package/dist/types.d.ts +30 -1
  57. package/package.json +69 -14
  58. package/src/build-output-transforms.ts +155 -21
  59. package/src/classic-mode.ts +253 -0
  60. package/src/config-imports.ts +153 -6
  61. package/src/constants.ts +6 -2
  62. package/src/dev-background-resources.ts +46 -85
  63. package/src/dev-generation.ts +52 -33
  64. package/src/dev-hmr.ts +112 -80
  65. package/src/dev-runtime-artifacts.ts +11 -12
  66. package/src/dev-runtime-controller.ts +75 -85
  67. package/src/dev-runtime-session.ts +14 -18
  68. package/src/dev-server.ts +2 -0
  69. package/src/dev-source-maps.ts +257 -0
  70. package/src/effect-runtime.ts +105 -57
  71. package/src/entry-paths.ts +80 -0
  72. package/src/environment-output.ts +55 -0
  73. package/src/export-utils.ts +15 -11
  74. package/src/index.ts +661 -496
  75. package/src/lazy-compilation-prewarm.ts +20 -4
  76. package/src/manifest.ts +157 -82
  77. package/src/mode-plan.ts +367 -0
  78. package/src/modify-browser-manifest.ts +130 -124
  79. package/src/plugin-utils.ts +103 -39
  80. package/src/prerender-build.ts +82 -104
  81. package/src/prerender.ts +23 -24
  82. package/src/react-router-config.ts +72 -26
  83. package/src/route-artifacts.ts +96 -66
  84. package/src/route-chunks.ts +167 -51
  85. package/src/route-component-transform.ts +14 -21
  86. package/src/route-export-pruning.ts +4 -3
  87. package/src/route-imports.ts +100 -0
  88. package/src/route-transform-tasks.ts +39 -25
  89. package/src/route-watch.ts +166 -188
  90. package/src/rsc-dev-server.ts +112 -0
  91. package/src/rsc-prerender.ts +362 -0
  92. package/src/rsc-route-config.ts +175 -0
  93. package/src/rsc-route-exports.ts +67 -0
  94. package/src/rsc-route-transform-loader.ts +65 -0
  95. package/src/rsc-route-transform-registration.ts +145 -0
  96. package/src/rsc-route-transforms.ts +995 -0
  97. package/src/rsc-runtime.d.ts +143 -0
  98. package/src/rsc-support.ts +116 -0
  99. package/src/rsc-virtual-modules.ts +113 -0
  100. package/src/server-build-plan.ts +14 -3
  101. package/src/server-build-resolution.ts +37 -47
  102. package/src/server-utils.ts +21 -35
  103. package/src/ssr-asset-relocation.ts +183 -0
  104. package/src/ssr-externals.ts +8 -26
  105. package/src/templates/entry.rsc.client.tsx +168 -0
  106. package/src/templates/entry.rsc.ssr.tsx +45 -0
  107. package/src/templates/entry.rsc.tsx +80 -0
  108. package/src/typegen.ts +40 -23
  109. package/src/types.ts +39 -1
  110. 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 type { RouteChunkConfig } from './route-chunks.js';
12
- import type { RouteTransformRunner } from './route-transform-tasks.js';
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
- type ReactRouterManifest = Awaited<
17
- ReturnType<typeof getReactRouterManifestForDev>
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: Parameters<typeof getReactRouterManifestForDev>[5];
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 transformRouteModule = async (args: Parameters<TransformHandler>[0]) =>
70
- performanceProfiler.record(
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
- routeChunkOptions
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
- performanceProfiler.record(
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
- routeTransformRunner({
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
+ };