rsbuild-plugin-react-router 0.4.1 → 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 (126) hide show
  1. package/README.md +72 -240
  2. package/dist/{451.js → 511.js} +461 -331
  3. package/dist/build-output-transforms.d.ts +32 -7
  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 -3
  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/federation.d.ts +2 -0
  17. package/dist/index.cjs +3675 -2107
  18. package/dist/index.d.ts +3 -1
  19. package/dist/index.js +3614 -2214
  20. package/dist/lazy-compilation-prewarm.d.ts +8 -5
  21. package/dist/manifest.d.ts +16 -4
  22. package/dist/mode-plan.d.ts +82 -0
  23. package/dist/modify-browser-manifest.d.ts +8 -4
  24. package/dist/performance.d.ts +4 -1
  25. package/dist/plugin-utils.d.ts +27 -1
  26. package/dist/prerender-build.d.ts +5 -5
  27. package/dist/prerender.d.ts +1 -5
  28. package/dist/react-router-config.d.ts +11 -3
  29. package/dist/route-artifacts.d.ts +4 -2
  30. package/dist/route-chunks.d.ts +2 -1
  31. package/dist/route-component-transform.d.ts +0 -2
  32. package/dist/route-export-pruning.d.ts +4 -1
  33. package/dist/route-imports.d.ts +18 -0
  34. package/dist/route-module-transform-loader.d.ts +14 -0
  35. package/dist/route-module-transform-loader.js +44 -0
  36. package/dist/route-module-transform-rules.d.ts +14 -0
  37. package/dist/route-transform-tasks.d.ts +6 -0
  38. package/dist/route-watch.d.ts +11 -6
  39. package/dist/rsc-dev-server.d.ts +26 -0
  40. package/dist/rsc-prerender.d.ts +54 -0
  41. package/dist/rsc-route-config.d.ts +6 -0
  42. package/dist/rsc-route-exports.d.ts +15 -0
  43. package/dist/rsc-route-transform-loader.cjs +43 -0
  44. package/dist/rsc-route-transform-loader.d.ts +30 -0
  45. package/dist/rsc-route-transform-loader.js +16 -0
  46. package/dist/rsc-route-transform-registration.d.ts +12 -0
  47. package/dist/rsc-route-transforms.d.ts +21 -0
  48. package/dist/rsc-support.d.ts +23 -0
  49. package/dist/rsc-virtual-modules.d.ts +19 -0
  50. package/dist/server-build-plan.d.ts +2 -1
  51. package/dist/server-build-resolution.d.ts +1 -2
  52. package/dist/server-utils.d.ts +4 -5
  53. package/dist/ssr-asset-relocation.d.ts +98 -0
  54. package/dist/templates/entry.rsc.client.d.ts +1 -0
  55. package/dist/templates/entry.rsc.client.js +61 -0
  56. package/dist/templates/entry.rsc.d.ts +9 -0
  57. package/dist/templates/entry.rsc.js +38 -0
  58. package/dist/templates/entry.rsc.ssr.d.ts +4 -0
  59. package/dist/templates/entry.rsc.ssr.js +24 -0
  60. package/dist/typegen.d.ts +4 -2
  61. package/dist/types.d.ts +34 -6
  62. package/package.json +76 -22
  63. package/src/build-output-transforms.ts +181 -43
  64. package/src/classic-mode.ts +253 -0
  65. package/src/config-imports.ts +153 -6
  66. package/src/constants.ts +6 -2
  67. package/src/dev-background-resources.ts +46 -100
  68. package/src/dev-generation.ts +52 -33
  69. package/src/dev-hmr.ts +112 -80
  70. package/src/dev-runtime-artifacts.ts +11 -12
  71. package/src/dev-runtime-controller.ts +75 -85
  72. package/src/dev-runtime-session.ts +14 -18
  73. package/src/dev-server.ts +2 -0
  74. package/src/dev-source-maps.ts +257 -0
  75. package/src/effect-runtime.ts +105 -57
  76. package/src/entry-paths.ts +80 -0
  77. package/src/environment-output.ts +55 -0
  78. package/src/export-utils.ts +15 -11
  79. package/src/federation.ts +38 -0
  80. package/src/index.ts +666 -519
  81. package/src/lazy-compilation-prewarm.ts +20 -4
  82. package/src/manifest.ts +157 -82
  83. package/src/mode-plan.ts +367 -0
  84. package/src/modify-browser-manifest.ts +130 -124
  85. package/src/performance.ts +11 -2
  86. package/src/plugin-utils.ts +103 -39
  87. package/src/prerender-build.ts +82 -104
  88. package/src/prerender.ts +23 -24
  89. package/src/react-router-config.ts +72 -26
  90. package/src/route-artifacts.ts +96 -66
  91. package/src/route-chunks.ts +167 -51
  92. package/src/route-component-transform.ts +14 -21
  93. package/src/route-export-pruning.ts +4 -3
  94. package/src/route-imports.ts +100 -0
  95. package/src/route-module-transform-loader.ts +149 -0
  96. package/src/route-module-transform-rules.ts +115 -0
  97. package/src/route-transform-tasks.ts +44 -29
  98. package/src/route-watch.ts +166 -188
  99. package/src/rsc-dev-server.ts +112 -0
  100. package/src/rsc-prerender.ts +362 -0
  101. package/src/rsc-route-config.ts +175 -0
  102. package/src/rsc-route-exports.ts +67 -0
  103. package/src/rsc-route-transform-loader.ts +65 -0
  104. package/src/rsc-route-transform-registration.ts +145 -0
  105. package/src/rsc-route-transforms.ts +995 -0
  106. package/src/rsc-runtime.d.ts +143 -0
  107. package/src/rsc-support.ts +116 -0
  108. package/src/rsc-virtual-modules.ts +113 -0
  109. package/src/server-build-plan.ts +14 -3
  110. package/src/server-build-resolution.ts +37 -47
  111. package/src/server-utils.ts +21 -35
  112. package/src/ssr-asset-relocation.ts +183 -0
  113. package/src/ssr-externals.ts +8 -26
  114. package/src/templates/entry.rsc.client.tsx +168 -0
  115. package/src/templates/entry.rsc.ssr.tsx +45 -0
  116. package/src/templates/entry.rsc.tsx +80 -0
  117. package/src/typegen.ts +40 -23
  118. package/src/types.ts +43 -6
  119. package/src/warnings/warn-on-client-source-maps.ts +6 -10
  120. package/dist/parallel-route-transform-protocol.d.ts +0 -25
  121. package/dist/parallel-route-transform-worker.d.ts +0 -1
  122. package/dist/parallel-route-transform-worker.js +0 -38
  123. package/dist/parallel-route-transforms.d.ts +0 -29
  124. package/src/parallel-route-transform-protocol.ts +0 -35
  125. package/src/parallel-route-transform-worker.ts +0 -82
  126. package/src/parallel-route-transforms.ts +0 -458
@@ -1,7 +1,12 @@
1
1
  import * as Effect from 'effect/Effect';
2
+ import type * as Scope from 'effect/Scope';
2
3
  import type { ReactRouterManifestForDev } from './manifest.js';
3
4
  import type { RouteManifestItem } from './types.js';
4
- import { createDelayedPluginTask, tryPluginPromise } from './effect-runtime.js';
5
+ import {
6
+ createDelayedPluginTask,
7
+ type PluginEffectRuntime,
8
+ tryPluginPromise,
9
+ } from './effect-runtime.js';
5
10
 
6
11
  const DEFAULT_LAZY_COMPILATION_TRIGGER_PREFIX = '/_rspack/lazy/trigger';
7
12
  const DEFAULT_PREWARM_DELAY_MS = 0;
@@ -9,17 +14,17 @@ const DEFAULT_ROUTE_PREWARM_LIMIT = 8;
9
14
  const PREWARM_FETCH_CONCURRENCY = 8;
10
15
  const PREWARM_TRIGGER_CANDIDATES = 4;
11
16
 
12
- type LazyCompilationPrewarmConfig = {
17
+ export type LazyCompilationPrewarmConfig = {
13
18
  entry: boolean;
14
19
  routeLimit: number;
15
20
  delayMs: number;
16
21
  };
17
22
 
18
- type LazyCompilationPrewarmController = {
23
+ export type LazyCompilationPrewarmController = {
19
24
  setServerOrigin(origin: string): void;
20
25
  setManifest(manifest: ReactRouterManifestForDev | null): void;
21
26
  schedule(): void;
22
- cancelEffect(): Effect.Effect<void, Error, never>;
27
+ cancelEffect(): Effect.Effect<void>;
23
28
  };
24
29
 
25
30
  export type RspackLazyCompilationTriggerClient = {
@@ -221,9 +226,11 @@ const prewarmLazyCompilation = ({
221
226
  });
222
227
 
223
228
  export const createLazyCompilationPrewarmController = ({
229
+ runtime,
224
230
  config,
225
231
  onError,
226
232
  }: {
233
+ runtime: PluginEffectRuntime;
227
234
  config: LazyCompilationPrewarmConfig;
228
235
  onError: (error: Error) => void;
229
236
  }): LazyCompilationPrewarmController => {
@@ -231,6 +238,7 @@ export const createLazyCompilationPrewarmController = ({
231
238
  let manifest: ReactRouterManifestForDev | null = null;
232
239
  let lastPrewarmAssetsKey: string | undefined;
233
240
  const task = createDelayedPluginTask({
241
+ runtime,
234
242
  delayMs: config.delayMs,
235
243
  run: () =>
236
244
  Effect.gen(function* () {
@@ -277,3 +285,11 @@ export const createLazyCompilationPrewarmController = ({
277
285
  },
278
286
  };
279
287
  };
288
+
289
+ export const acquireLazyCompilationPrewarm = (
290
+ options: Parameters<typeof createLazyCompilationPrewarmController>[0]
291
+ ): Effect.Effect<LazyCompilationPrewarmController, never, Scope.Scope> =>
292
+ Effect.acquireRelease(
293
+ Effect.sync(() => createLazyCompilationPrewarmController(options)),
294
+ controller => controller.cancelEffect()
295
+ );
package/src/manifest.ts CHANGED
@@ -3,7 +3,11 @@ import { dirname, isAbsolute, relative, resolve } from 'pathe';
3
3
  import * as Effect from 'effect/Effect';
4
4
  import type { Route, PluginOptions, RouteManifestItem } from './types.js';
5
5
  import { combineURLs, createRouteId } from './plugin-utils.js';
6
- import { SERVER_EXPORTS, CLIENT_EXPORTS } from './constants.js';
6
+ import {
7
+ CLIENT_EXPORTS,
8
+ DEFAULT_JS_DIST_PATH,
9
+ SERVER_EXPORTS,
10
+ } from './constants.js';
7
11
  import {
8
12
  buildManifestChunkValidity,
9
13
  createEmptyRouteChunkByExportName,
@@ -13,8 +17,12 @@ import {
13
17
  validateRouteChunks,
14
18
  type RouteChunkCache,
15
19
  type RouteChunkConfig,
20
+ type RouteChunkExportName,
16
21
  } from './route-chunks.js';
17
- import { getRouteModuleAnalysis } from './export-utils.js';
22
+ import {
23
+ getRouteModuleAnalysis,
24
+ type RouteModuleAnalysis,
25
+ } from './export-utils.js';
18
26
  import { getCappedPluginConcurrency } from './concurrency.js';
19
27
  import { runPluginEffect, tryPluginPromise } from './effect-runtime.js';
20
28
 
@@ -87,13 +95,38 @@ export function configRoutesToRouteManifestEntries(
87
95
  return routeManifestEntries;
88
96
  }
89
97
 
90
- type RouteChunkManifestOptions = {
98
+ export type RouteChunkManifestOptions = {
91
99
  splitRouteModules?: boolean | 'enforce';
92
100
  rootRouteFile?: string;
93
101
  isBuild?: boolean;
94
102
  cache?: RouteChunkCache;
95
103
  };
96
104
 
105
+ export type RouteModuleAnalysisProvider = (
106
+ routeFilePath: string,
107
+ route: Route
108
+ ) => Promise<RouteModuleAnalysis | undefined>;
109
+
110
+ export type ReactRouterManifestOptions = RouteChunkManifestOptions & {
111
+ routeModuleAnalysis?: RouteModuleAnalysisProvider;
112
+ };
113
+
114
+ export const createReactRouterManifestOptions = ({
115
+ routeChunks,
116
+ routeModuleAnalysis,
117
+ }: {
118
+ routeChunks?: RouteChunkManifestOptions;
119
+ routeModuleAnalysis?: RouteModuleAnalysisProvider;
120
+ }): ReactRouterManifestOptions | undefined => {
121
+ if (!routeChunks && !routeModuleAnalysis) {
122
+ return undefined;
123
+ }
124
+ return {
125
+ ...routeChunks,
126
+ ...(routeModuleAnalysis ? { routeModuleAnalysis } : {}),
127
+ };
128
+ };
129
+
97
130
  export type ReactRouterManifestForDev = {
98
131
  version: string;
99
132
  url: string;
@@ -122,8 +155,10 @@ type ReactRouterManifestStatsEntrypoint = {
122
155
  getFiles?: () => Iterable<string>;
123
156
  };
124
157
 
125
- type ReactRouterManifestStatsLookup<T> = Iterable<[string, T]> & {
126
- get?: (name: string) => T | undefined;
158
+ type ReactRouterManifestStatsLookup<T> = Iterable<
159
+ [string, T | null | undefined]
160
+ > & {
161
+ get?: (name: string) => T | null | undefined;
127
162
  };
128
163
 
129
164
  type ReactRouterManifestStatsCompilation = {
@@ -153,6 +188,9 @@ const collectManifestFilesByName = <T>(
153
188
  const filesByName: Record<string, string[]> = {};
154
189
  if (!names) {
155
190
  for (const [name, item] of items) {
191
+ if (item == null) {
192
+ continue;
193
+ }
156
194
  filesByName[name] = getFiles(name, item);
157
195
  }
158
196
  return filesByName;
@@ -162,7 +200,7 @@ const collectManifestFilesByName = <T>(
162
200
  if (typeof items.get === 'function') {
163
201
  for (const name of names) {
164
202
  const item = items.get(name);
165
- if (!item) {
203
+ if (item == null) {
166
204
  continue;
167
205
  }
168
206
  filesByName[name] = getFiles(name, item);
@@ -178,6 +216,9 @@ const collectManifestFilesByName = <T>(
178
216
  if (!missingNames.has(name)) {
179
217
  continue;
180
218
  }
219
+ if (item == null) {
220
+ continue;
221
+ }
181
222
  filesByName[name] = getFiles(name, item);
182
223
  missingNames.delete(name);
183
224
  if (missingNames.size === 0) {
@@ -236,11 +277,12 @@ type RouteManifestAnalysis = {
236
277
  > | null;
237
278
  };
238
279
 
239
- const DEFAULT_MANIFEST_DIR = 'static/js';
280
+ const DEFAULT_MANIFEST_DIR = DEFAULT_JS_DIST_PATH;
240
281
  const CSS_IMPORT_RE = /\.(?:css|less|sass|scss)(?:\?[^'"`]+)?['"`]/;
241
282
 
242
283
  const createChunkAssetResolver = (
243
- clientStats: ReactRouterManifestStats | undefined
284
+ clientStats: ReactRouterManifestStats | undefined,
285
+ includeEntrypointJs: boolean
244
286
  ): ((chunkName: string) => ChunkAssets) => {
245
287
  const chunkAssetsByName = new Map<string, ChunkAssets>();
246
288
 
@@ -259,24 +301,26 @@ const createChunkAssetResolver = (
259
301
  }
260
302
 
261
303
  const cssAssets = new Set<string>();
262
- const jsAssets: string[] = [];
304
+ const jsAssets = new Set<string>();
263
305
  for (const asset of assets) {
264
306
  if (asset.endsWith('.css')) {
265
307
  cssAssets.add(asset);
266
308
  } else if (asset.endsWith('.js')) {
267
- jsAssets.push(asset);
309
+ jsAssets.add(asset);
268
310
  }
269
311
  }
270
312
  for (const asset of clientStats?.entrypointFilesByName?.[chunkName] ?? []) {
271
313
  if (asset.endsWith('.css')) {
272
314
  cssAssets.add(asset);
315
+ } else if (includeEntrypointJs && asset.endsWith('.js')) {
316
+ jsAssets.add(asset);
273
317
  }
274
318
  }
275
- if (jsAssets.length === 0) {
276
- jsAssets.push(`${DEFAULT_MANIFEST_DIR}/${chunkName}.js`);
319
+ if (jsAssets.size === 0) {
320
+ jsAssets.add(`${DEFAULT_MANIFEST_DIR}/${chunkName}.js`);
277
321
  }
278
322
 
279
- const result = { js: jsAssets, css: [...cssAssets] };
323
+ const result = { js: [...jsAssets], css: [...cssAssets] };
280
324
  chunkAssetsByName.set(chunkName, result);
281
325
  return result;
282
326
  };
@@ -289,6 +333,8 @@ const analyzeRouteForManifestEffect = ({
289
333
  routeChunkConfig,
290
334
  routeEntryName,
291
335
  routeFilePath,
336
+ route,
337
+ routeModuleAnalysis,
292
338
  }: {
293
339
  discoveredCssAssets: string[];
294
340
  isBuild: boolean;
@@ -296,10 +342,13 @@ const analyzeRouteForManifestEffect = ({
296
342
  routeChunkConfig: RouteChunkConfig | null;
297
343
  routeEntryName: string;
298
344
  routeFilePath: string;
345
+ route: Route;
346
+ routeModuleAnalysis?: RouteModuleAnalysisProvider;
299
347
  }): Effect.Effect<RouteManifestAnalysis, Error, never> =>
300
348
  tryPluginPromise(async () => {
301
349
  const { code, exports: exportNames } =
302
- await getRouteModuleAnalysis(routeFilePath);
350
+ (await routeModuleAnalysis?.(routeFilePath, route)) ??
351
+ (await getRouteModuleAnalysis(routeFilePath));
303
352
  const cssAssets =
304
353
  !isBuild && discoveredCssAssets.length === 0 && CSS_IMPORT_RE.test(code)
305
354
  ? [
@@ -398,33 +447,94 @@ export const getReactRouterManifestChunkNames = (
398
447
  return chunkNames;
399
448
  };
400
449
 
450
+ const createRouteManifestItem = ({
451
+ route,
452
+ assetPrefix,
453
+ jsAssets,
454
+ routeAnalysis,
455
+ getModulePathForChunk,
456
+ getCssAssetsForChunk,
457
+ }: {
458
+ route: Route;
459
+ assetPrefix: string;
460
+ jsAssets: string[];
461
+ routeAnalysis: RouteManifestAnalysis;
462
+ getModulePathForChunk: (chunkName: string) => string | undefined;
463
+ getCssAssetsForChunk: (chunkName: string) => string[];
464
+ }): RouteManifestItem => {
465
+ const routeChunkMap = routeAnalysis.hasRouteChunkByExportName;
466
+ const chunkModulePath = (exportName: RouteChunkExportName) =>
467
+ routeChunkMap?.[exportName]
468
+ ? getModulePathForChunk(getRouteChunkEntryName(route.id, exportName))
469
+ : undefined;
470
+ const cssAssets = [
471
+ ...routeAnalysis.cssAssets,
472
+ ...routeChunkExportNames.flatMap(exportName =>
473
+ routeChunkMap?.[exportName]
474
+ ? getCssAssetsForChunk(getRouteChunkEntryName(route.id, exportName))
475
+ : []
476
+ ),
477
+ ];
478
+
479
+ return {
480
+ id: route.id,
481
+ parentId: route.parentId,
482
+ path: route.path,
483
+ index: route.index,
484
+ caseSensitive: route.caseSensitive,
485
+ module: combineURLs(assetPrefix, jsAssets[0] || ''),
486
+ clientActionModule: chunkModulePath('clientAction'),
487
+ clientLoaderModule: chunkModulePath('clientLoader'),
488
+ clientMiddlewareModule: chunkModulePath('clientMiddleware'),
489
+ hydrateFallbackModule: chunkModulePath('HydrateFallback'),
490
+ hasAction: routeAnalysis.exports.has(SERVER_EXPORTS.action),
491
+ hasLoader: routeAnalysis.exports.has(SERVER_EXPORTS.loader),
492
+ hasClientAction: routeAnalysis.exports.has(CLIENT_EXPORTS.clientAction),
493
+ hasClientLoader: routeAnalysis.exports.has(CLIENT_EXPORTS.clientLoader),
494
+ hasClientMiddleware: routeAnalysis.exports.has(
495
+ CLIENT_EXPORTS.clientMiddleware
496
+ ),
497
+ hasDefaultExport: routeAnalysis.exports.has('default'),
498
+ hasErrorBoundary: routeAnalysis.exports.has(CLIENT_EXPORTS.ErrorBoundary),
499
+ // `module` is `jsAssets[0]`; exclude it from `imports` so the browser
500
+ // manifest does not list the route's own module twice (upstream excludes
501
+ // the entry chunk's own file from its imports list). Otherwise prefetch
502
+ // link computations produce duplicate modulepreload hrefs.
503
+ imports: jsAssets.slice(1).map(asset => combineURLs(assetPrefix, asset)),
504
+ css: Array.from(new Set(cssAssets)).map(asset =>
505
+ combineURLs(assetPrefix, asset)
506
+ ),
507
+ };
508
+ };
509
+
401
510
  function generateReactRouterManifestForDevEffect(
402
511
  routes: Record<string, Route>,
403
- _options: PluginOptions,
404
512
  clientStats: ReactRouterManifestStats | undefined,
405
513
  context: string,
406
514
  assetPrefix: string,
407
- routeChunkOptions?: RouteChunkManifestOptions
515
+ manifestOptions?: ReactRouterManifestOptions
408
516
  ): Effect.Effect<ReactRouterManifestGenerationResult, Error, never> {
409
517
  return Effect.gen(function* () {
410
518
  const result: Record<string, RouteManifestItem> = {};
411
- const splitRouteModules = routeChunkOptions?.splitRouteModules ?? false;
519
+ const splitRouteModules = manifestOptions?.splitRouteModules ?? false;
412
520
  const enforceSplitRouteModules = splitRouteModules === 'enforce';
413
- const isBuild = routeChunkOptions?.isBuild ?? false;
521
+ const isBuild = manifestOptions?.isBuild ?? false;
414
522
  const routeChunkConfig: RouteChunkConfig | null =
415
- splitRouteModules && routeChunkOptions?.rootRouteFile
523
+ splitRouteModules && manifestOptions?.rootRouteFile
416
524
  ? {
417
525
  splitRouteModules,
418
526
  appDirectory: context,
419
- rootRouteFile: routeChunkOptions.rootRouteFile,
527
+ rootRouteFile: manifestOptions.rootRouteFile,
420
528
  }
421
529
  : null;
422
530
 
423
- const getAssetsForChunk = createChunkAssetResolver(clientStats);
531
+ const getAssetsForChunk = createChunkAssetResolver(clientStats, isBuild);
424
532
  const getModulePathForChunk = (chunkName: string): string | undefined => {
425
533
  const { js: jsAssets } = getAssetsForChunk(chunkName);
426
534
  return jsAssets[0] ? combineURLs(assetPrefix, jsAssets[0]) : undefined;
427
535
  };
536
+ const getCssAssetsForChunk = (chunkName: string): string[] =>
537
+ getAssetsForChunk(chunkName).css;
428
538
 
429
539
  const manifestEntries = yield* Effect.forEach(
430
540
  Object.entries(routes),
@@ -437,78 +547,36 @@ function generateReactRouterManifestForDevEffect(
437
547
  const routeAnalysis = yield* analyzeRouteForManifestEffect({
438
548
  discoveredCssAssets,
439
549
  isBuild,
440
- routeChunkCache: routeChunkOptions?.cache,
550
+ routeChunkCache: manifestOptions?.cache,
441
551
  routeChunkConfig,
442
552
  routeEntryName,
443
553
  routeFilePath,
554
+ route,
555
+ routeModuleAnalysis: manifestOptions?.routeModuleAnalysis,
444
556
  });
445
557
 
446
- const hasClientAction = routeAnalysis.exports.has(
447
- CLIENT_EXPORTS.clientAction
448
- );
449
- const hasClientLoader = routeAnalysis.exports.has(
450
- CLIENT_EXPORTS.clientLoader
451
- );
452
- const hasClientMiddleware = routeAnalysis.exports.has(
453
- CLIENT_EXPORTS.clientMiddleware
454
- );
455
- const hasDefaultExport = routeAnalysis.exports.has('default');
456
- const routeChunkMap = routeAnalysis.hasRouteChunkByExportName;
457
-
458
558
  if (isBuild && enforceSplitRouteModules && routeChunkConfig) {
459
559
  validateRouteChunks({
460
560
  config: routeChunkConfig,
461
561
  id: routeFilePath,
462
562
  valid: buildManifestChunkValidity(
463
563
  routeAnalysis.exports,
464
- routeChunkMap ?? createEmptyRouteChunkByExportName()
564
+ routeAnalysis.hasRouteChunkByExportName ??
565
+ createEmptyRouteChunkByExportName()
465
566
  ),
466
567
  });
467
568
  }
468
569
 
469
570
  return [
470
571
  key,
471
- {
472
- id: route.id,
473
- parentId: route.parentId,
474
- path: route.path,
475
- index: route.index,
476
- caseSensitive: route.caseSensitive,
477
- module: combineURLs(assetPrefix, jsAssets[0] || ''),
478
- clientActionModule: routeChunkMap?.clientAction
479
- ? getModulePathForChunk(
480
- getRouteChunkEntryName(route.id, 'clientAction')
481
- )
482
- : undefined,
483
- clientLoaderModule: routeChunkMap?.clientLoader
484
- ? getModulePathForChunk(
485
- getRouteChunkEntryName(route.id, 'clientLoader')
486
- )
487
- : undefined,
488
- clientMiddlewareModule: routeChunkMap?.clientMiddleware
489
- ? getModulePathForChunk(
490
- getRouteChunkEntryName(route.id, 'clientMiddleware')
491
- )
492
- : undefined,
493
- hydrateFallbackModule: routeChunkMap?.HydrateFallback
494
- ? getModulePathForChunk(
495
- getRouteChunkEntryName(route.id, 'HydrateFallback')
496
- )
497
- : undefined,
498
- hasAction: routeAnalysis.exports.has(SERVER_EXPORTS.action),
499
- hasLoader: routeAnalysis.exports.has(SERVER_EXPORTS.loader),
500
- hasClientAction,
501
- hasClientLoader,
502
- hasClientMiddleware,
503
- hasDefaultExport,
504
- hasErrorBoundary: routeAnalysis.exports.has(
505
- CLIENT_EXPORTS.ErrorBoundary
506
- ),
507
- imports: jsAssets.map(asset => combineURLs(assetPrefix, asset)),
508
- css: routeAnalysis.cssAssets.map(asset =>
509
- combineURLs(assetPrefix, asset)
510
- ),
511
- },
572
+ createRouteManifestItem({
573
+ route,
574
+ assetPrefix,
575
+ jsAssets,
576
+ routeAnalysis,
577
+ getModulePathForChunk,
578
+ getCssAssetsForChunk,
579
+ }),
512
580
  routeAnalysis.routeModuleExports,
513
581
  ] as const;
514
582
  }),
@@ -536,7 +604,12 @@ function generateReactRouterManifestForDevEffect(
536
604
  const fingerprintedValues = {
537
605
  entry: {
538
606
  module: combineURLs(assetPrefix, entryJsAssets[0] || ''),
539
- imports: entryJsAssets.map(asset => combineURLs(assetPrefix, asset)),
607
+ // Exclude the entry's own module (`entryJsAssets[0]`) from imports so it
608
+ // is not listed twice, matching upstream where `imports` holds only the
609
+ // chunk's dependency imports.
610
+ imports: entryJsAssets
611
+ .slice(1)
612
+ .map(asset => combineURLs(assetPrefix, asset)),
540
613
  css: entryCssAssets.map(asset => combineURLs(assetPrefix, asset)),
541
614
  },
542
615
  routes: result,
@@ -550,7 +623,10 @@ function generateReactRouterManifestForDevEffect(
550
623
 
551
624
  const manifest = {
552
625
  version,
553
- url: combineURLs(assetPrefix, manifestPath),
626
+ url: combineURLs(
627
+ assetPrefix,
628
+ isBuild ? manifestPath : `${manifestPath}?v=${version}`
629
+ ),
554
630
  hmr: undefined,
555
631
  entry: fingerprintedValues.entry,
556
632
  sri: undefined,
@@ -566,20 +642,19 @@ function generateReactRouterManifestForDevEffect(
566
642
 
567
643
  export async function generateReactRouterManifestForDev(
568
644
  routes: Record<string, Route>,
569
- options: PluginOptions,
645
+ _options: PluginOptions,
570
646
  clientStats: ReactRouterManifestStats | undefined,
571
647
  context: string,
572
648
  assetPrefix = '/',
573
- routeChunkOptions?: RouteChunkManifestOptions
649
+ manifestOptions?: ReactRouterManifestOptions
574
650
  ): Promise<ReactRouterManifestGenerationResult> {
575
651
  return runPluginEffect(
576
652
  generateReactRouterManifestForDevEffect(
577
653
  routes,
578
- options,
579
654
  clientStats,
580
655
  context,
581
656
  assetPrefix,
582
- routeChunkOptions
657
+ manifestOptions
583
658
  )
584
659
  );
585
660
  }