rsbuild-plugin-react-router 0.2.0 → 0.3.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 (96) hide show
  1. package/README.md +185 -204
  2. package/dist/451.js +1087 -0
  3. package/dist/bounded-cache.d.ts +1 -0
  4. package/dist/build-manifest.d.ts +1 -1
  5. package/dist/build-output-transforms.d.ts +30 -0
  6. package/dist/concurrency.d.ts +2 -0
  7. package/dist/config-imports.d.ts +3 -0
  8. package/dist/constants.d.ts +3 -0
  9. package/dist/dev-generation.d.ts +25 -0
  10. package/dist/dev-runtime-artifacts.d.ts +39 -0
  11. package/dist/dev-runtime-compilation.d.ts +32 -0
  12. package/dist/dev-runtime-controller.d.ts +14 -0
  13. package/dist/dev-runtime-session.d.ts +34 -0
  14. package/dist/dev-server.d.ts +11 -2
  15. package/dist/export-utils.d.ts +15 -7
  16. package/dist/index.cjs +3050 -1244
  17. package/dist/index.d.ts +4 -1
  18. package/dist/index.js +2015 -1279
  19. package/dist/lazy-compilation.d.ts +5 -0
  20. package/dist/manifest.d.ts +32 -9
  21. package/dist/modify-browser-manifest.d.ts +30 -13
  22. package/dist/parallel-route-transform-protocol.d.ts +25 -0
  23. package/dist/parallel-route-transform-worker.d.ts +1 -0
  24. package/dist/parallel-route-transform-worker.js +38 -0
  25. package/dist/parallel-route-transforms.d.ts +14 -0
  26. package/dist/performance.d.ts +26 -0
  27. package/dist/plugin-utils.d.ts +2 -12
  28. package/dist/prerender-build.d.ts +32 -0
  29. package/dist/prerender.d.ts +28 -2
  30. package/dist/react-router-config.d.ts +8 -1
  31. package/dist/route-artifacts.d.ts +33 -0
  32. package/dist/route-ast.d.ts +21 -0
  33. package/dist/route-chunks.d.ts +9 -1
  34. package/dist/route-component-transform.d.ts +5 -0
  35. package/dist/route-export-pruning.d.ts +6 -0
  36. package/dist/route-export-resolution.d.ts +5 -0
  37. package/dist/route-transform-tasks.d.ts +47 -0
  38. package/dist/route-watch.d.ts +27 -0
  39. package/dist/server-build-plan.d.ts +22 -0
  40. package/dist/server-utils.d.ts +3 -2
  41. package/dist/templates/entry.server.cjs +3 -3
  42. package/dist/templates/entry.server.js +3 -3
  43. package/dist/typegen.d.ts +2 -0
  44. package/dist/types.d.ts +30 -12
  45. package/dist/virtual-modules.d.ts +2 -0
  46. package/dist/warnings/warn-on-client-source-maps.d.ts +1 -0
  47. package/dist/yuku.d.ts +15 -0
  48. package/package.json +22 -19
  49. package/src/bounded-cache.ts +18 -0
  50. package/src/build-manifest.ts +168 -0
  51. package/src/build-output-transforms.ts +273 -0
  52. package/src/concurrency.ts +34 -0
  53. package/src/config-imports.ts +45 -0
  54. package/src/constants.ts +91 -0
  55. package/src/dev-generation.ts +700 -0
  56. package/src/dev-runtime-artifacts.ts +207 -0
  57. package/src/dev-runtime-compilation.ts +92 -0
  58. package/src/dev-runtime-controller.ts +462 -0
  59. package/src/dev-runtime-session.ts +184 -0
  60. package/src/dev-server.ts +58 -0
  61. package/src/export-utils.ts +219 -0
  62. package/src/index.ts +1025 -0
  63. package/src/lazy-compilation.ts +94 -0
  64. package/src/manifest.ts +480 -0
  65. package/src/modify-browser-manifest.ts +245 -0
  66. package/src/parallel-route-transform-protocol.ts +35 -0
  67. package/src/parallel-route-transform-worker.ts +82 -0
  68. package/src/parallel-route-transforms.ts +332 -0
  69. package/src/performance.ts +254 -0
  70. package/src/plugin-utils.ts +82 -0
  71. package/src/prerender-build.ts +623 -0
  72. package/src/prerender.ts +367 -0
  73. package/src/react-router-config.ts +220 -0
  74. package/src/route-artifacts.ts +155 -0
  75. package/src/route-ast.ts +163 -0
  76. package/src/route-chunks.ts +857 -0
  77. package/src/route-component-transform.ts +314 -0
  78. package/src/route-config.ts +106 -0
  79. package/src/route-export-pruning.ts +668 -0
  80. package/src/route-export-resolution.ts +329 -0
  81. package/src/route-transform-tasks.ts +249 -0
  82. package/src/route-watch.ts +322 -0
  83. package/src/server-build-plan.ts +91 -0
  84. package/src/server-utils.ts +210 -0
  85. package/src/ssr-externals.ts +59 -0
  86. package/src/templates/context.ts +12 -0
  87. package/src/templates/entry.client.tsx +12 -0
  88. package/src/templates/entry.server.tsx +76 -0
  89. package/src/typegen.ts +49 -0
  90. package/src/types.ts +82 -0
  91. package/src/validation/validate-plugin-order.ts +76 -0
  92. package/src/virtual-modules.ts +30 -0
  93. package/src/warnings/warn-on-client-source-maps.ts +96 -0
  94. package/src/yuku.ts +67 -0
  95. package/dist/0~rslib-runtime.js +0 -16
  96. package/dist/babel.d.ts +0 -8
package/dist/index.js CHANGED
@@ -1,68 +1,25 @@
1
- let lexer_C;
2
- import { __webpack_require__ } from "./0~rslib-runtime.js";
3
- import { existsSync, readFileSync, realpathSync, statSync } from "node:fs";
4
- import { mkdir, readFile, writeFile } from "node:fs/promises";
5
- import { createRequire } from "node:module";
6
- import { pathToFileURL, fileURLToPath as __rspack_fileURLToPath } from "node:url";
1
+ import { existsSync, readFileSync, realpathSync, watch } from "node:fs";
7
2
  import fs_extra from "fs-extra";
3
+ import { rspack } from "@rsbuild/core";
8
4
  import { createJiti } from "jiti";
9
- import jsesc from "jsesc";
10
- import { basename as external_pathe_basename, dirname, extname, isAbsolute, normalize, relative, resolve } from "pathe";
11
- import { RspackVirtualModulePlugin } from "rspack-plugin-virtual-module";
12
- import { parse } from "@babel/parser";
13
- import { callExpression, functionExpression, identifier as types_identifier, importDeclaration, importSpecifier, isClassDeclaration, isExportAllDeclaration, isExportDeclaration, isExportDefaultDeclaration, isExportNamedDeclaration, isFunctionDeclaration, isIdentifier, isImportDeclaration, isNodesEquivalent, isObjectProperty, isPattern, isRestElement, isStatement, isVariableDeclaration, isVariableDeclarator, stringLiteral, variableDeclaration, variableDeclarator as types_variableDeclarator } from "@babel/types";
14
- import { deadCodeElimination, findReferencedIdentifiers } from "babel-dead-code-elimination";
5
+ import { dirname, isAbsolute, relative, resolve as external_pathe_resolve } from "pathe";
6
+ import { createRequestHandler as external_react_router_createRequestHandler, matchRoutes } from "react-router";
7
+ import { access, mkdir, readdir, writeFile } from "node:fs/promises";
8
+ import { pathToFileURL, fileURLToPath as __rspack_fileURLToPath } from "node:url";
15
9
  import { createHash } from "node:crypto";
16
- import { rspack } from "@rsbuild/core";
17
- import { createRequestHandler, matchRoutes } from "react-router";
18
- import { sep, dirname as __rspack_dirname } from "node:path";
19
- import * as __rspack_external_esbuild from "esbuild";
20
- let generator_namespaceObject = require("@babel/generator");
21
- var A, A1, ImportType, generator_default = __webpack_require__.n(generator_namespaceObject);
22
- let traverse_namespaceObject = require("@babel/traverse");
23
- var traverse_default = __webpack_require__.n(traverse_namespaceObject);
24
- let traverse = traverse_default().default ?? traverse_default(), generate = generator_default().default ?? generator_default(), PLUGIN_NAME = 'rsbuild:react-router', JS_EXTENSIONS = [
25
- '.tsx',
26
- '.ts',
27
- '.jsx',
28
- '.js',
29
- '.mjs',
30
- '.mts'
31
- ], JS_LOADERS = {
32
- '.ts': 'ts',
33
- '.tsx': 'tsx',
34
- '.js': 'js',
35
- '.jsx': 'jsx',
36
- '.mjs': 'js',
37
- '.mts': 'ts'
38
- }, BUILD_CLIENT_ROUTE_QUERY_STRING = '?__react-router-build-client-route', SERVER_ONLY_ROUTE_EXPORTS = [
39
- 'loader',
40
- 'action',
41
- 'middleware',
42
- 'headers'
43
- ], CLIENT_ROUTE_EXPORTS = [
44
- 'clientAction',
45
- 'clientLoader',
46
- 'clientMiddleware',
47
- 'handle',
48
- 'meta',
49
- 'links',
50
- 'shouldRevalidate',
51
- 'default',
52
- 'ErrorBoundary',
53
- 'HydrateFallback',
54
- 'Layout'
55
- ], NAMED_COMPONENT_EXPORTS = [
56
- 'HydrateFallback',
57
- 'ErrorBoundary'
58
- ];
10
+ import { availableParallelism, cpus } from "node:os";
11
+ import jsesc from "jsesc";
12
+ import { Worker } from "node:worker_threads";
13
+ import { createRequire } from "node:module";
14
+ import { isAbsolute as external_node_path_isAbsolute, relative as external_node_path_relative, sep, dirname as __rspack_dirname } from "node:path";
15
+ import { createRouteId, SERVER_EXPORTS, combineURLs, JS_EXTENSIONS, executeRouteTransformTask, setBoundedCacheEntry, PLUGIN_NAME, generateWithProps, getRouteModuleAnalysis, createEmptyRouteChunkByExportName, findEntryFile, routeChunkExportNames, validateRouteChunks, CLIENT_EXPORTS, buildManifestChunkValidity, BUILD_CLIENT_ROUTE_QUERY_STRING, getRouteChunkEntryName, getRouteChunkModuleId, normalizeAssetPrefix, detectRouteChunksIfEnabled, createBundlerRouteExportResolver } from "./451.js";
59
16
  function generateServerBuild(routes, options) {
60
17
  let manifestId;
61
18
  return manifestId = options.serverManifestId ?? 'virtual/react-router/server-manifest', `
62
19
  import * as entryServer from ${JSON.stringify(options.entryServerPath)};
63
20
  ${Object.keys(routes).map((key, index)=>{
64
21
  let route = routes[key];
65
- return `import * as route${index} from ${JSON.stringify(`${resolve(options.appDirectory, route.file)}?react-router-route`)};`;
22
+ return `import * as route${index} from ${JSON.stringify(`${external_pathe_resolve(options.appDirectory, route.file)}?react-router-route`)};`;
66
23
  }).join('\n')}
67
24
 
68
25
  export { default as assets } from ${JSON.stringify(manifestId)};
@@ -103,7 +60,14 @@ let RESOLVABLE_BUILD_EXPORTS = new Set([
103
60
  'routeDiscovery',
104
61
  'routes',
105
62
  'ssr'
106
- ]), isPromiseLike = (value)=>'function' == typeof value?.then, normalizeBuildModule = (build)=>build && 'object' == typeof build && 'default' in build && 1 === Object.keys(build).length && 'object' == typeof build.default && build.default ? build.default : build, resolveBuildExports = async (build)=>{
63
+ ]);
64
+ function isRecord(value) {
65
+ return 'object' == typeof value && null !== value && !Array.isArray(value);
66
+ }
67
+ function isPromiseLike(value) {
68
+ return isRecord(value) && 'function' == typeof value.then;
69
+ }
70
+ async function resolveBuildExports(build) {
107
71
  let resolved = {
108
72
  ...build
109
73
  };
@@ -118,30 +82,56 @@ let RESOLVABLE_BUILD_EXPORTS = new Set([
118
82
  isPromiseLike(value) && (resolved[key] = await value);
119
83
  }
120
84
  return resolved;
121
- };
122
- function invalidDestructureError(name) {
123
- return Error(`Cannot remove destructured export "${name}"`);
124
- }
125
- function toFunctionExpression(decl) {
126
- return functionExpression(decl.id, decl.params, decl.body, decl.generator, decl.async);
127
85
  }
128
- function combineURLs(baseURL, relativeURL) {
129
- return relativeURL ? `${baseURL.replace(/\/+$/, '')}/${relativeURL.replace(/^\/+/, '')}` : baseURL;
86
+ async function resolveServerBuildCandidate(candidate) {
87
+ var value;
88
+ if (!isRecord(candidate)) return;
89
+ let resolved = await resolveBuildExports(candidate);
90
+ return isRecord(resolved) && isRecord(resolved.entry) && isRecord(resolved.entry.module) && 'function' == typeof resolved.entry.module.default && isRecord(resolved.routes) && isRecord(resolved.assets) && 'string' == typeof resolved.assetsBuildDirectory && (void 0 === resolved.basename || 'string' == typeof resolved.basename) && isRecord(resolved.future) && 'boolean' == typeof resolved.isSpaMode && Array.isArray(resolved.prerender) && 'string' == typeof resolved.publicPath && isRecord(value = resolved.routeDiscovery) && ('initial' === value.mode || 'lazy' === value.mode && (void 0 === value.manifestPath || 'string' == typeof value.manifestPath)) && 'boolean' == typeof resolved.ssr ? resolved : void 0;
130
91
  }
131
- function normalizeAssetPrefix(assetPrefix) {
132
- return assetPrefix && 'auto' !== assetPrefix ? assetPrefix.endsWith('/') ? assetPrefix : `${assetPrefix}/` : '/';
133
- }
134
- function findEntryFile(basePath) {
135
- for (let ext of JS_EXTENSIONS){
136
- let filePath = `${basePath}${ext}`;
137
- if (existsSync(filePath)) return filePath;
92
+ async function resolveServerBuildModule(buildModule, source) {
93
+ let moduleValue = await buildModule, candidates = [
94
+ ()=>moduleValue
95
+ ];
96
+ for (let getCandidate of (isRecord(moduleValue) && ('default' in moduleValue && candidates.push(()=>moduleValue.default), 'module.exports' in moduleValue && candidates.push(()=>moduleValue['module.exports'])), candidates)){
97
+ let candidate = await getCandidate(), serverBuild = await resolveServerBuildCandidate(candidate);
98
+ if (serverBuild) return serverBuild;
138
99
  }
139
- return `${basePath}.tsx`;
100
+ throw Error(`[rsbuild-plugin-react-router] ${source} did not contain a valid React Router ServerBuild.`);
140
101
  }
141
- function isNamedComponentExport(name) {
142
- return NAMED_COMPONENT_EXPORTS.includes(name);
102
+ function resolveReactRouterServerBuild(buildModule) {
103
+ return resolveServerBuildModule(buildModule, 'Imported module');
143
104
  }
144
- let normalizePath = (value)=>value.replace(/\/\/+/g, '/').replace(/(.+)\/$/, '$1'), resolvePrerenderPaths = async (prerender, ssr, routes, options = {})=>{
105
+ let normalizePath = (value)=>value.replace(/\/\/+/g, '/').replace(/(.+)\/$/, '$1'), groupRoutesByParentId = (manifest)=>{
106
+ let grouped = {};
107
+ return Object.values(manifest).forEach((route)=>{
108
+ if (!route) return;
109
+ let parentId = route.parentId || '';
110
+ grouped[parentId] ??= [], grouped[parentId].push(route);
111
+ }), grouped;
112
+ }, createPrerenderRoutes = (manifest, parentId = '', grouped = groupRoutesByParentId(manifest))=>(grouped[parentId] || []).map((route)=>{
113
+ let common = {
114
+ id: route.id,
115
+ path: route.path
116
+ };
117
+ return route.index ? {
118
+ index: !0,
119
+ ...common
120
+ } : {
121
+ ...common,
122
+ children: createPrerenderRoutes(manifest, route.id, grouped)
123
+ };
124
+ }), normalizePrerenderMatchPath = (path)=>`/${path}/`.replace(/^\/\/+/, '/'), withBuildRequest = async (input, init, handle)=>{
125
+ let controller = new AbortController();
126
+ try {
127
+ return await handle(new Request(input, {
128
+ ...init,
129
+ signal: controller.signal
130
+ }));
131
+ } finally{
132
+ controller.abort();
133
+ }
134
+ }, resolvePrerenderPaths = async (prerender, ssr, routes, options = {})=>{
145
135
  let pathsConfig, paths, paramRoutes, recurse;
146
136
  if (null == prerender || !1 === prerender || !1 === (pathsConfig = 'object' == typeof prerender && null !== prerender && 'paths' in prerender ? prerender?.paths : prerender)) return [];
147
137
  let { paths: paths1, paramRoutes: paramRoutes1 } = (paths = [
@@ -182,12 +172,392 @@ let normalizePath = (value)=>value.replace(/\/\/+/g, '/').replace(/(.+)\/$/, '$1
182
172
  return !0 === resolved ? paths1 : !1 === resolved || null == resolved ? [] : resolved;
183
173
  }
184
174
  return pathsConfig ?? [];
185
- }, isValidPrerenderPathsConfig = (value)=>'boolean' == typeof value || 'function' == typeof value || Array.isArray(value), DEFAULT_CONFIG = {
175
+ }, getPrerenderConfigObject = (prerender)=>'object' != typeof prerender || null === prerender || Array.isArray(prerender) ? null : prerender, getPrerenderConcurrencyConfig = (config)=>config?.concurrency !== void 0 ? {
176
+ key: 'prerender.concurrency',
177
+ value: config.concurrency
178
+ } : config?.unstable_concurrency !== void 0 ? {
179
+ key: 'prerender.unstable_concurrency',
180
+ value: config.unstable_concurrency
181
+ } : void 0, getAvailableCpuCount = ()=>'function' == typeof availableParallelism ? availableParallelism() : cpus().length, getDefaultConcurrency = (cpuCount = getAvailableCpuCount())=>Math.max(0, Math.floor(cpuCount) - 2), mapWithConcurrency = async (items, concurrency, worker)=>{
182
+ let results = Array(items.length), nextIndex = 0, workerCount = Math.max(1, Math.min(concurrency, items.length));
183
+ return await Promise.all(Array.from({
184
+ length: workerCount
185
+ }, async ()=>{
186
+ for(;;){
187
+ let index = nextIndex++;
188
+ if (index >= items.length) return;
189
+ results[index] = await worker(items[index], index);
190
+ }
191
+ })), results;
192
+ }, ROUTE_ANALYSIS_CONCURRENCY = Math.max(1, Math.min(16, getDefaultConcurrency() || 1));
193
+ function configRoutesToRouteManifestEntries(appDirectory, routes, rootId = 'root') {
194
+ let routeManifestEntries = [], routeIds = new Set();
195
+ for (let route of routes)!function walk(route, parentId) {
196
+ let id = route.id || createRouteId(route.file), manifestItem = {
197
+ id,
198
+ parentId,
199
+ file: isAbsolute(route.file) ? relative(appDirectory, route.file) : route.file,
200
+ path: route.path,
201
+ index: route.index,
202
+ caseSensitive: route.caseSensitive
203
+ };
204
+ if (routeIds.has(id)) throw Error(`Unable to define routes with duplicate route id: "${id}"`);
205
+ if (routeIds.add(id), routeManifestEntries.push([
206
+ id,
207
+ manifestItem
208
+ ]), route.children) for (let child of route.children)walk(child, id);
209
+ }(route, rootId);
210
+ return routeManifestEntries;
211
+ }
212
+ let orderChunkFiles = (chunkName, files)=>{
213
+ let ownChunkAsset = `${chunkName}.js`, ownFileIndex = files.findIndex((file)=>file.endsWith(ownChunkAsset));
214
+ return ownFileIndex <= 0 ? files : [
215
+ files[ownFileIndex],
216
+ ...files.slice(0, ownFileIndex),
217
+ ...files.slice(ownFileIndex + 1)
218
+ ];
219
+ }, createReactRouterManifestStats = (compilation, chunkNames)=>{
220
+ if (!compilation) return;
221
+ let assetsByChunkName = {}, entrypointFilesByName = {}, namedChunks = compilation.namedChunks, entrypoints = compilation.entrypoints;
222
+ if (chunkNames && 'function' == typeof namedChunks.get) for (let chunkName of chunkNames){
223
+ let chunk = namedChunks.get(chunkName);
224
+ if (!chunk) continue;
225
+ let files = Array.from(chunk.files ?? []);
226
+ assetsByChunkName[chunkName] = orderChunkFiles(chunkName, files);
227
+ }
228
+ else for (let [chunkName, chunk] of namedChunks){
229
+ if (chunkNames && !chunkNames.has(chunkName)) continue;
230
+ let files = Array.from(chunk.files ?? []);
231
+ assetsByChunkName[chunkName] = orderChunkFiles(chunkName, files);
232
+ }
233
+ if (entrypoints) if (chunkNames && 'function' == typeof entrypoints.get) for (let entrypointName of chunkNames){
234
+ let entrypoint = entrypoints.get(entrypointName);
235
+ entrypoint && (entrypointFilesByName[entrypointName] = Array.from(entrypoint.getFiles?.() ?? []));
236
+ }
237
+ else for (let [entrypointName, entrypoint] of entrypoints)(!chunkNames || chunkNames.has(entrypointName)) && (entrypointFilesByName[entrypointName] = Array.from(entrypoint.getFiles?.() ?? []));
238
+ return Object.keys(entrypointFilesByName).length > 0 ? {
239
+ assetsByChunkName,
240
+ entrypointFilesByName
241
+ } : {
242
+ assetsByChunkName
243
+ };
244
+ }, DEFAULT_MANIFEST_DIR = 'static/js', getReactRouterManifestPath = ({ version, isBuild, entryModulePath })=>{
245
+ if (!isBuild) return 'static/js/virtual/react-router/browser-manifest.js';
246
+ let dir = ((entryModulePath)=>{
247
+ if (!entryModulePath) return DEFAULT_MANIFEST_DIR;
248
+ let dir = dirname(entryModulePath);
249
+ return '.' === dir ? DEFAULT_MANIFEST_DIR : dir;
250
+ })(entryModulePath);
251
+ return `${dir}/manifest-${version}.js`;
252
+ }, getRouteEntryName = (route)=>{
253
+ let extensionIndex = route.file.lastIndexOf('.');
254
+ return extensionIndex >= 0 ? route.file.slice(0, extensionIndex) : route.file;
255
+ };
256
+ async function generateReactRouterManifestForDev(routes, _options, clientStats, context, assetPrefix = '/', routeChunkOptions) {
257
+ let result = {}, splitRouteModules = routeChunkOptions?.splitRouteModules ?? !1, enforceSplitRouteModules = 'enforce' === splitRouteModules, isBuild = routeChunkOptions?.isBuild ?? !1, routeChunkConfig = splitRouteModules && routeChunkOptions?.rootRouteFile ? {
258
+ splitRouteModules,
259
+ appDirectory: context,
260
+ rootRouteFile: routeChunkOptions.rootRouteFile
261
+ } : null, getAssetsForChunk = (chunkName)=>{
262
+ let assets = clientStats?.assetsByChunkName?.[chunkName];
263
+ if (!assets) return [
264
+ `${DEFAULT_MANIFEST_DIR}/${chunkName}.js`
265
+ ];
266
+ let entrypointCssAssets = clientStats?.entrypointFilesByName?.[chunkName]?.filter((asset)=>asset.endsWith('.css')) ?? [], cssAssets = [
267
+ ...assets.filter((asset)=>asset.endsWith('.css')),
268
+ ...entrypointCssAssets
269
+ ].filter((asset, index, all)=>all.indexOf(asset) === index), nonCssAssets = assets.filter((asset)=>!asset.endsWith('.css'));
270
+ return nonCssAssets.some((asset)=>asset.endsWith('.js')) ? [
271
+ ...nonCssAssets,
272
+ ...cssAssets
273
+ ] : [
274
+ `${DEFAULT_MANIFEST_DIR}/${chunkName}.js`,
275
+ ...nonCssAssets,
276
+ ...cssAssets
277
+ ];
278
+ }, getModulePathForChunk = (chunkName)=>{
279
+ let jsAssets = getAssetsForChunk(chunkName).filter((asset)=>asset.endsWith('.js'));
280
+ return jsAssets[0] ? combineURLs(assetPrefix, jsAssets[0]) : void 0;
281
+ }, manifestEntries = await mapWithConcurrency(Object.entries(routes), ROUTE_ANALYSIS_CONCURRENCY, async ([key, route])=>{
282
+ let routeEntryName = getRouteEntryName(route), assets = getAssetsForChunk(routeEntryName), jsAssets = assets.filter((asset)=>asset.endsWith('.js')), cssAssets = assets.filter((asset)=>asset.endsWith('.css')), routeFilePath = external_pathe_resolve(context, route.file), exports = new Set(), routeModuleExports = [], hasRouteChunkByExportName = null;
283
+ try {
284
+ let { code, exports: exportNames } = await getRouteModuleAnalysis(routeFilePath);
285
+ if (!isBuild && 0 === cssAssets.length && /\.(?:css|less|sass|scss)(?:\?[^'"`]+)?['"`]/.test(code) && (cssAssets = [
286
+ `${DEFAULT_MANIFEST_DIR.replace('/js', '/css')}/${routeEntryName}.css`
287
+ ]), routeModuleExports = exportNames, exports = new Set(exportNames), isBuild && routeChunkConfig) {
288
+ let { hasRouteChunkByExportName: chunkInfo } = await detectRouteChunksIfEnabled(routeChunkOptions?.cache, routeChunkConfig, routeFilePath, code);
289
+ hasRouteChunkByExportName = chunkInfo;
290
+ }
291
+ } catch (error) {
292
+ if (isBuild) throw error;
293
+ console.error(`Failed to analyze route file ${routeFilePath}:`, error);
294
+ }
295
+ let hasClientAction = exports.has(CLIENT_EXPORTS.clientAction), hasClientLoader = exports.has(CLIENT_EXPORTS.clientLoader), hasClientMiddleware = exports.has(CLIENT_EXPORTS.clientMiddleware), hasDefaultExport = exports.has('default'), routeChunkMap = hasRouteChunkByExportName;
296
+ return isBuild && enforceSplitRouteModules && routeChunkConfig && validateRouteChunks({
297
+ config: routeChunkConfig,
298
+ id: routeFilePath,
299
+ valid: buildManifestChunkValidity(exports, routeChunkMap ?? createEmptyRouteChunkByExportName())
300
+ }), [
301
+ key,
302
+ {
303
+ id: route.id,
304
+ parentId: route.parentId,
305
+ path: route.path,
306
+ index: route.index,
307
+ caseSensitive: route.caseSensitive,
308
+ module: combineURLs(assetPrefix, jsAssets[0] || ''),
309
+ clientActionModule: routeChunkMap?.clientAction ? getModulePathForChunk(getRouteChunkEntryName(route.id, 'clientAction')) : void 0,
310
+ clientLoaderModule: routeChunkMap?.clientLoader ? getModulePathForChunk(getRouteChunkEntryName(route.id, 'clientLoader')) : void 0,
311
+ clientMiddlewareModule: routeChunkMap?.clientMiddleware ? getModulePathForChunk(getRouteChunkEntryName(route.id, 'clientMiddleware')) : void 0,
312
+ hydrateFallbackModule: routeChunkMap?.HydrateFallback ? getModulePathForChunk(getRouteChunkEntryName(route.id, 'HydrateFallback')) : void 0,
313
+ hasAction: exports.has(SERVER_EXPORTS.action),
314
+ hasLoader: exports.has(SERVER_EXPORTS.loader),
315
+ hasClientAction,
316
+ hasClientLoader,
317
+ hasClientMiddleware,
318
+ hasDefaultExport,
319
+ hasErrorBoundary: exports.has(CLIENT_EXPORTS.ErrorBoundary),
320
+ imports: jsAssets.map((asset)=>combineURLs(assetPrefix, asset)),
321
+ css: cssAssets.map((asset)=>combineURLs(assetPrefix, asset))
322
+ },
323
+ routeModuleExports
324
+ ];
325
+ }), routeModuleExportsByRouteId = {};
326
+ for (let [key, routeManifestItem, routeModuleExports] of manifestEntries)result[key] = routeManifestItem, routeModuleExportsByRouteId[key] = routeModuleExports;
327
+ let entryAssets = getAssetsForChunk('entry.client'), entryJsAssets = entryAssets.filter((asset)=>asset.endsWith('.js')), entryCssAssets = entryAssets.filter((asset)=>asset.endsWith('.css')), fingerprintedValues = {
328
+ entry: {
329
+ module: combineURLs(assetPrefix, entryJsAssets[0] || ''),
330
+ imports: entryJsAssets.map((asset)=>combineURLs(assetPrefix, asset)),
331
+ css: entryCssAssets.map((asset)=>combineURLs(assetPrefix, asset))
332
+ },
333
+ routes: result
334
+ }, version = isBuild ? createHash('md5').update(JSON.stringify(fingerprintedValues)).digest('hex').slice(0, 8) : String(Math.random()), manifestPath = getReactRouterManifestPath({
335
+ version,
336
+ isBuild,
337
+ entryModulePath: entryJsAssets[0]
338
+ });
339
+ return {
340
+ manifest: {
341
+ version,
342
+ url: combineURLs(assetPrefix, manifestPath),
343
+ hmr: void 0,
344
+ entry: fingerprintedValues.entry,
345
+ sri: void 0,
346
+ routes: result
347
+ },
348
+ moduleExportsByRouteId: routeModuleExportsByRouteId
349
+ };
350
+ }
351
+ async function getReactRouterManifestForDev(...args) {
352
+ return (await generateReactRouterManifestForDev(...args)).manifest;
353
+ }
354
+ let redirectStatusCodes = new Set([
355
+ 301,
356
+ 302,
357
+ 303,
358
+ 307,
359
+ 308
360
+ ]), getServerBuildPath = async ({ buildDirectory, serverBuildFile })=>{
361
+ let serverBuildDir = external_pathe_resolve(buildDirectory, 'server'), defaultServerBuildFile = 'static/js/app.js', configuredServerBuildFile = serverBuildFile || 'index.js', configuredServerBuildPath = external_pathe_resolve(serverBuildDir, configuredServerBuildFile), defaultServerBuildPath = external_pathe_resolve(serverBuildDir, defaultServerBuildFile);
362
+ return configuredServerBuildFile !== defaultServerBuildFile && existsSync(defaultServerBuildPath) && !existsSync(configuredServerBuildPath) && (await mkdir(dirname(configuredServerBuildPath), {
363
+ recursive: !0
364
+ }), await fs_extra.copy(defaultServerBuildPath, configuredServerBuildPath)), {
365
+ serverBuildDir,
366
+ serverBuildPath: existsSync(configuredServerBuildPath) ? configuredServerBuildPath : defaultServerBuildPath
367
+ };
368
+ }, prerenderData = async ({ handler, prerenderPath, onlyRoutes, clientBuildDir, basename, trailingSlashAwareDataRequests, api, requestInit })=>{
369
+ let dataRequestPath = trailingSlashAwareDataRequests ? prerenderPath.endsWith('/') ? `${prerenderPath}_.data` : `${prerenderPath}.data` : '/' === prerenderPath ? '/_root.data' : `${prerenderPath.replace(/\/$/, '')}.data`, normalizedPath = `${basename}${dataRequestPath}`.replace(/\/\/+/g, '/'), url = new URL(`http://localhost${normalizedPath}`);
370
+ return onlyRoutes?.length && url.searchParams.set('_routes', onlyRoutes.join(',')), withBuildRequest(url, requestInit, async (request)=>{
371
+ let response = await handler(request), data = await response.text();
372
+ if (200 !== response.status && 202 !== response.status) throw Error(`Prerender (data): Received a ${response.status} status code from \`entry.server.tsx\` while prerendering the \`${prerenderPath}\` path.\n${normalizedPath}`);
373
+ let outputPath = external_pathe_resolve(clientBuildDir, ...normalizedPath.split('/'));
374
+ return await mkdir(dirname(outputPath), {
375
+ recursive: !0
376
+ }), await writeFile(outputPath, data), api.logger.info(`Prerender (data): ${prerenderPath} -> ${relative(process.cwd(), outputPath)}`), data;
377
+ });
378
+ }, prerenderRoute = async ({ handler, prerenderPath, clientBuildDir, basename, api, requestInit })=>{
379
+ let normalizedPath = `${basename}${prerenderPath}/`.replace(/\/\/+/g, '/');
380
+ await withBuildRequest(`http://localhost${normalizedPath}`, requestInit, async (request)=>{
381
+ let response = await handler(request), html = await response.text();
382
+ if (redirectStatusCodes.has(response.status)) {
383
+ let location = response.headers.get('Location'), delay = 2 * (302 === response.status);
384
+ html = `<!doctype html>
385
+ <head>
386
+ <title>Redirecting to: ${location}</title>
387
+ <meta http-equiv="refresh" content="${delay};url=${location}">
388
+ <meta name="robots" content="noindex">
389
+ </head>
390
+ <body>
391
+ \t<a href="${location}">
392
+ Redirecting from <code>${normalizedPath}</code> to <code>${location}</code>
393
+ </a>
394
+ </body>
395
+ </html>`;
396
+ } else if (200 !== response.status) throw Error(`Prerender (html): Received a ${response.status} status code from \`entry.server.tsx\` while prerendering the \`${normalizedPath}\` path.\n` + html);
397
+ let outputPath = external_pathe_resolve(clientBuildDir, ...normalizedPath.split('/'), 'index.html');
398
+ await mkdir(dirname(outputPath), {
399
+ recursive: !0
400
+ }), await writeFile(outputPath, html), api.logger.info(`Prerender (html): ${prerenderPath} -> ${relative(process.cwd(), outputPath)}`);
401
+ });
402
+ }, prerenderResourceRoute = async ({ handler, prerenderPath, clientBuildDir, basename, api, requestInit })=>{
403
+ let normalizedPath = `${basename}${prerenderPath}/`.replace(/\/\/+/g, '/').replace(/\/$/g, '');
404
+ await withBuildRequest(`http://localhost${normalizedPath}`, requestInit, async (request)=>{
405
+ let response = await handler(request), content = Buffer.from(await response.arrayBuffer());
406
+ if (200 !== response.status) throw Error(`Prerender (resource): Received a ${response.status} status code from \`entry.server.tsx\` while prerendering the \`${normalizedPath}\` path.\n` + content.toString('utf8'));
407
+ let outputPath = external_pathe_resolve(clientBuildDir, ...normalizedPath.split('/'));
408
+ await mkdir(dirname(outputPath), {
409
+ recursive: !0
410
+ }), await writeFile(outputPath, content), api.logger.info(`Prerender (resource): ${prerenderPath} -> ${relative(process.cwd(), outputPath)}`);
411
+ });
412
+ }, handleSpaMode = async ({ handler, build, clientBuildDir, basename, api })=>{
413
+ await withBuildRequest(`http://localhost${basename}`, {
414
+ headers: {
415
+ 'X-React-Router-SPA-Mode': 'yes'
416
+ }
417
+ }, async (request)=>{
418
+ let response = await handler(request), html = await response.text(), isPrerenderSpaFallback = build.prerender?.includes('/'), filename = isPrerenderSpaFallback ? '__spa-fallback.html' : 'index.html';
419
+ if (200 !== response.status) {
420
+ if (isPrerenderSpaFallback) throw Error(`Prerender: Received a ${response.status} status code from \`entry.server.tsx\` while prerendering your \`${filename}\` file.\n` + html);
421
+ throw Error(`SPA Mode: Received a ${response.status} status code from \`entry.server.tsx\` while prerendering your \`${filename}\` file.\n` + html);
422
+ }
423
+ if (!html.includes('window.__reactRouterContext =') || !html.includes('window.__reactRouterRouteModules =')) throw Error("SPA Mode: Did you forget to include `<Scripts/>` in your root route? Your pre-rendered HTML cannot hydrate without `<Scripts />`.");
424
+ let outputPath = external_pathe_resolve(clientBuildDir, filename);
425
+ await writeFile(outputPath, html);
426
+ let prettyPath = relative(process.cwd(), outputPath);
427
+ build.prerender?.length ? api.logger.info(`Prerender (html): SPA Fallback -> ${prettyPath}`) : api.logger.info(`SPA Mode: Generated ${prettyPath}`);
428
+ });
429
+ }, runPrerenderPaths = async ({ build, requestHandler, clientBuildDir, options })=>{
430
+ let config, value, { api, basename, future, prerenderConfig, prerenderPaths } = options, buildRoutes = createPrerenderRoutes(build.routes), concurrency = (config = getPrerenderConfigObject(prerenderConfig), 'number' == typeof (value = getPrerenderConcurrencyConfig(config)?.value) && Number.isInteger(value) && value > 0 ? value : 1), pending = new Set(), enqueue = async (path)=>{
431
+ let data, matches = matchRoutes(buildRoutes, normalizePrerenderMatchPath(path));
432
+ if (!matches) return;
433
+ let leafRoute = matches[matches.length - 1]?.route, routeId = leafRoute?.id, manifestRoute = routeId ? build.routes?.[routeId]?.module : null;
434
+ !manifestRoute || manifestRoute.default || manifestRoute.ErrorBoundary ? (matches.some((match)=>{
435
+ let matchedRouteId = match.route.id;
436
+ return !!matchedRouteId && build.assets?.routes?.[matchedRouteId]?.hasLoader;
437
+ }) && (data = await prerenderData({
438
+ handler: requestHandler,
439
+ prerenderPath: path,
440
+ onlyRoutes: null,
441
+ clientBuildDir,
442
+ basename,
443
+ trailingSlashAwareDataRequests: future.unstable_trailingSlashAwareDataRequests,
444
+ api
445
+ })), await prerenderRoute({
446
+ handler: requestHandler,
447
+ prerenderPath: path,
448
+ clientBuildDir,
449
+ basename,
450
+ api,
451
+ requestInit: data ? {
452
+ headers: {
453
+ 'X-React-Router-Prerender-Data': encodeURI(data)
454
+ }
455
+ } : void 0
456
+ })) : manifestRoute.loader && routeId ? (await prerenderData({
457
+ handler: requestHandler,
458
+ prerenderPath: path,
459
+ onlyRoutes: [
460
+ routeId
461
+ ],
462
+ clientBuildDir,
463
+ basename,
464
+ trailingSlashAwareDataRequests: future.unstable_trailingSlashAwareDataRequests,
465
+ api
466
+ }), await prerenderResourceRoute({
467
+ handler: requestHandler,
468
+ prerenderPath: path,
469
+ clientBuildDir,
470
+ basename,
471
+ api
472
+ })) : api.logger.warn(`⚠️ Skipping prerendering for resource route without a loader: ${routeId}`);
473
+ };
474
+ for (let path of prerenderPaths){
475
+ let task = enqueue(path);
476
+ pending.add(task), task.finally(()=>pending.delete(task)), pending.size >= concurrency && await Promise.race(pending);
477
+ }
478
+ await Promise.all(pending);
479
+ }, runReactRouterPrerenderBuild = async (options)=>{
480
+ if (!options.hasWebEnvironment) return;
481
+ let { api, buildDirectory, serverBuildFile, ssr, isPrerenderEnabled, prerenderPaths, routes, latestBrowserManifest, latestBrowserManifestModuleExports, clientStats, pluginOptions, appDirectory, assetPrefix, routeChunkOptions, buildManifest, resolvedConfigWithRoutes, buildEnd, basename } = options, { serverBuildDir, serverBuildPath } = await getServerBuildPath({
482
+ buildDirectory,
483
+ serverBuildFile
484
+ }), clientBuildDir = external_pathe_resolve(buildDirectory, 'client');
485
+ if (!existsSync(serverBuildPath)) return void console.warn(`[${PLUGIN_NAME}] Server build not found at ${serverBuildPath}. Skipping prerendering.`);
486
+ if (await mkdir(clientBuildDir, {
487
+ recursive: !0
488
+ }), !ssr || isPrerenderEnabled) {
489
+ process.env.IS_RR_BUILD_REQUEST = 'yes';
490
+ let buildModule = await import(pathToFileURL(serverBuildPath).toString()), build = await resolveServerBuildModule(buildModule, `Server build ${JSON.stringify(serverBuildPath)}`), requestHandler = external_react_router_createRequestHandler(build, 'production');
491
+ if (isPrerenderEnabled) {
492
+ if (!ssr) {
493
+ let generated = latestBrowserManifest ? {
494
+ manifest: latestBrowserManifest,
495
+ moduleExportsByRouteId: latestBrowserManifestModuleExports
496
+ } : await generateReactRouterManifestForDev(routes, pluginOptions, clientStats, appDirectory, assetPrefix, routeChunkOptions);
497
+ (({ routes, manifestRoutes, routeExports, prerenderPaths, api })=>{
498
+ let errors = (({ routes, manifestRoutes, routeExports, prerenderPaths })=>{
499
+ if (0 === prerenderPaths.length) return [];
500
+ let prerenderRoutes = createPrerenderRoutes(routes), prerenderedRoutes = new Set();
501
+ for (let path of prerenderPaths){
502
+ let matches = matchRoutes(prerenderRoutes, normalizePrerenderMatchPath(path));
503
+ if (!matches) throw Error(`Unable to prerender path because it does not match any routes: ${path}`);
504
+ matches.forEach((match)=>prerenderedRoutes.add(match.route.id));
505
+ }
506
+ let errors = [];
507
+ for (let [routeId, route] of Object.entries(manifestRoutes)){
508
+ let exports = routeExports[routeId] ?? [], invalidApis = [];
509
+ if (exports.includes('headers') && invalidApis.push('headers'), exports.includes('action') && invalidApis.push('action'), invalidApis.length > 0 && errors.push(`Prerender: ${invalidApis.length} invalid route export(s) in \`${routeId}\` when pre-rendering with \`ssr:false\`: ${invalidApis.map((api)=>`\`${api}\``).join(', ')}. See https://reactrouter.com/how-to/pre-rendering#invalid-exports for more information.`), !prerenderedRoutes.has(routeId)) {
510
+ exports.includes('loader') && errors.push(`Prerender: 1 invalid route export in \`${routeId}\` when pre-rendering with \`ssr:false\`: \`loader\`. See https://reactrouter.com/how-to/pre-rendering#invalid-exports for more information.`);
511
+ let parentRoute = route.parentId && manifestRoutes[route.parentId] ? manifestRoutes[route.parentId] : null;
512
+ for(; parentRoute;)parentRoute.hasLoader && !parentRoute.hasClientLoader && errors.push(`Prerender: 1 invalid route export in \`${parentRoute.id}\` when pre-rendering with \`ssr:false\`: \`loader\`. See https://reactrouter.com/how-to/pre-rendering#invalid-exports for more information.`), parentRoute = parentRoute.parentId && manifestRoutes[parentRoute.parentId] ? manifestRoutes[parentRoute.parentId] : null;
513
+ }
514
+ }
515
+ return errors;
516
+ })({
517
+ routes,
518
+ manifestRoutes,
519
+ routeExports,
520
+ prerenderPaths
521
+ });
522
+ if (errors.length > 0) throw api.logger.error(errors.join('\n')), Error('Invalid route exports found when prerendering with `ssr:false`');
523
+ })({
524
+ routes,
525
+ manifestRoutes: generated.manifest.routes,
526
+ routeExports: generated.moduleExportsByRouteId,
527
+ prerenderPaths,
528
+ api
529
+ });
530
+ }
531
+ let routeTree = createPrerenderRoutes(routes);
532
+ for (let path of prerenderPaths)if (!matchRoutes(routeTree, normalizePrerenderMatchPath(path))) throw Error(`Unable to prerender path because it does not match any routes: ${path}`);
533
+ prerenderPaths.length > 0 && api.logger.info(`Prerender (html): ${prerenderPaths.length} path(s)...`), await runPrerenderPaths({
534
+ build,
535
+ requestHandler,
536
+ clientBuildDir,
537
+ options
538
+ });
539
+ }
540
+ ssr || await handleSpaMode({
541
+ handler: requestHandler,
542
+ build,
543
+ clientBuildDir,
544
+ basename,
545
+ api
546
+ });
547
+ }
548
+ ssr || (await fs_extra.remove(serverBuildDir), api.logger.info(`[${PLUGIN_NAME}] Removed server build (static deployment)`)), buildEnd && await buildEnd({
549
+ buildManifest,
550
+ reactRouterConfig: resolvedConfigWithRoutes,
551
+ viteConfig: api.getNormalizedConfig()
552
+ });
553
+ }, DEFAULT_CONFIG = {
186
554
  appDirectory: 'app',
187
555
  basename: '/',
188
556
  buildDirectory: 'build',
189
557
  serverBuildFile: 'index.js',
190
558
  serverModuleFormat: 'esm',
559
+ splitRouteModules: !0,
560
+ subResourceIntegrity: !1,
191
561
  ssr: !0,
192
562
  future: {
193
563
  unstable_optimizeDeps: !1,
@@ -204,6 +574,16 @@ let normalizePath = (value)=>value.replace(/\/\/+/g, '/').replace(/(.+)\/$/, '$1
204
574
  allowedActionOrigins: !1,
205
575
  routes: {},
206
576
  unstable_routeConfig: []
577
+ }, normalizeSubResourceIntegrity = (config)=>{
578
+ let subResourceIntegrity = config.subResourceIntegrity ?? config.future?.unstable_subResourceIntegrity;
579
+ return void 0 === subResourceIntegrity ? config : {
580
+ ...config,
581
+ subResourceIntegrity,
582
+ future: {
583
+ ...config.future ?? {},
584
+ unstable_subResourceIntegrity: subResourceIntegrity
585
+ }
586
+ };
207
587
  }, resolveReactRouterConfig = async (reactRouterUserConfig)=>{
208
588
  let userAndPresetConfigs = ((...configs)=>configs.reduce((configA, configB)=>{
209
589
  let mergeRequired = (key)=>void 0 !== configA[key] && void 0 !== configB[key];
@@ -240,495 +620,337 @@ let normalizePath = (value)=>value.replace(/\/\/+/g, '/').replace(/(.+)\/$/, '$1
240
620
  if (!presetConfig) return null;
241
621
  let { presets: _presets, ...rest } = presetConfig;
242
622
  return rest;
243
- }))).filter(Boolean), reactRouterUserConfig), resolvedFuture = {
623
+ }))).filter(Boolean).map(normalizeSubResourceIntegrity), normalizeSubResourceIntegrity(reactRouterUserConfig)), subResourceIntegrity = userAndPresetConfigs.subResourceIntegrity ?? userAndPresetConfigs.future?.unstable_subResourceIntegrity ?? DEFAULT_CONFIG.subResourceIntegrity, resolvedFuture = {
244
624
  ...DEFAULT_CONFIG.future,
245
- ...userAndPresetConfigs.future ?? {}
246
- }, resolved = {
625
+ ...userAndPresetConfigs.future ?? {},
626
+ unstable_subResourceIntegrity: subResourceIntegrity
627
+ }, splitRouteModules = userAndPresetConfigs.splitRouteModules ?? userAndPresetConfigs.future?.v8_splitRouteModules ?? DEFAULT_CONFIG.splitRouteModules, resolved = {
247
628
  ...DEFAULT_CONFIG,
248
629
  ...userAndPresetConfigs,
249
630
  future: resolvedFuture,
631
+ splitRouteModules,
632
+ subResourceIntegrity,
250
633
  allowedActionOrigins: userAndPresetConfigs.allowedActionOrigins ?? DEFAULT_CONFIG.allowedActionOrigins,
251
634
  routes: DEFAULT_CONFIG.routes,
252
- unstable_routeConfig: DEFAULT_CONFIG.unstable_routeConfig,
253
- serverBundles: DEFAULT_CONFIG.serverBundles
635
+ unstable_routeConfig: DEFAULT_CONFIG.unstable_routeConfig
254
636
  };
255
637
  return resolved.ssr || (resolved = {
256
638
  ...resolved,
257
639
  serverBundles: void 0
258
640
  }), {
259
641
  resolved,
260
- presets: reactRouterUserConfig.presets ?? []
261
- };
262
- }, routeChunkExportNames = [
263
- 'clientAction',
264
- 'clientLoader',
265
- 'clientMiddleware',
266
- 'HydrateFallback'
267
- ];
268
- [
269
- ...routeChunkExportNames
270
- ];
271
- let routeChunkQueryStringPrefix = '?route-chunk=', routeChunkQueryStrings = {
272
- main: `${routeChunkQueryStringPrefix}main`,
273
- clientAction: `${routeChunkQueryStringPrefix}clientAction`,
274
- clientLoader: `${routeChunkQueryStringPrefix}clientLoader`,
275
- clientMiddleware: `${routeChunkQueryStringPrefix}clientMiddleware`,
276
- HydrateFallback: `${routeChunkQueryStringPrefix}HydrateFallback`
277
- }, routeChunkEntrySuffix = {
278
- clientAction: 'client-action',
279
- clientLoader: 'client-loader',
280
- clientMiddleware: 'client-middleware',
281
- HydrateFallback: 'hydrate-fallback'
282
- }, invariant = (value, message)=>{
283
- if (!value) throw Error(message);
284
- }, getOrSetFromCache = (cache, key, version, getValue)=>{
285
- if (!cache) return getValue();
286
- let entry = cache.get(key);
287
- if (entry?.version === version) return entry.value;
288
- let value = getValue();
289
- return cache.set(key, {
290
- value,
291
- version
292
- }), value;
293
- }, codeToAst = (code, cache, cacheKey)=>structuredClone(getOrSetFromCache(cache, `${cacheKey}::codeToAst`, code, ()=>parse(code, {
294
- sourceType: 'module'
295
- }))), isNodePathWithNode = (path)=>!(!path || 'object' != typeof path || Array.isArray(path)) && 'node' in path && !!path.node, assertNodePathIsVariableDeclarator = (path)=>{
296
- invariant(path && !Array.isArray(path) && isVariableDeclarator(path.node), `Expected a VariableDeclarator path, but got ${Array.isArray(path) ? 'an array' : path?.node?.type}`);
297
- }, assertNodePathIsPattern = (path)=>{
298
- invariant(path && !Array.isArray(path) && isPattern(path.node), `Expected a Pattern path, but got ${Array.isArray(path) ? 'an array' : path?.node?.type}`);
299
- }, getExportDependencies = (code, cache, cacheKey)=>getOrSetFromCache(cache, `${cacheKey}::getExportDependencies`, code, ()=>{
300
- let exportDependencies = new Map();
301
- function handleExport(exportName, exportPath, identifiersPath = exportPath) {
302
- let identifiers = getDependentIdentifiersForPath(identifiersPath), topLevelStatements = new Set([
303
- exportPath.node,
304
- ...getTopLevelStatementsForPaths(identifiers)
305
- ]), topLevelNonModuleStatements = new Set(Array.from(topLevelStatements).filter((statement)=>!isImportDeclaration(statement) && !isExportDeclaration(statement))), importedIdentifierNames = new Set();
306
- for (let identifier of identifiers)isIdentifier(identifier.node) && identifier.parentPath?.parentPath?.isImportDeclaration() && importedIdentifierNames.add(identifier.node.name);
307
- let exportedVariableDeclarators = new Set();
308
- for (let identifier of identifiers){
309
- if (identifier.parentPath?.isVariableDeclarator()) {
310
- let parentPath = identifier.parentPath;
311
- if (parentPath.parentPath?.parentPath?.isExportNamedDeclaration()) {
312
- exportedVariableDeclarators.add(parentPath.node);
313
- continue;
314
- }
315
- }
316
- if (identifier.findParent((path)=>!!(path.isPattern() && path.parentPath?.isVariableDeclarator() && path.parentPath.parentPath?.parentPath?.isExportNamedDeclaration()))) {
317
- let currentPath = identifier;
318
- for(; currentPath;){
319
- if (currentPath.parentPath?.isVariableDeclarator() && 'id' === currentPath.parentKey) {
320
- exportedVariableDeclarators.add(currentPath.parentPath.node);
321
- break;
322
- }
323
- currentPath = currentPath.parentPath;
324
- }
325
- }
326
- }
327
- exportDependencies.set(exportName, {
328
- topLevelStatements,
329
- topLevelNonModuleStatements,
330
- importedIdentifierNames,
331
- exportedVariableDeclarators
332
- });
333
- }
334
- return traverse(codeToAst(code, cache, cacheKey), {
335
- ExportDeclaration (exportPath) {
336
- let { node } = exportPath;
337
- if (isExportAllDeclaration(node)) return;
338
- if (isExportDefaultDeclaration(node)) return void handleExport('default', exportPath);
339
- let { declaration } = node;
340
- if (isVariableDeclaration(declaration)) {
341
- let { declarations } = declaration;
342
- for(let i = 0; i < declarations.length; i++){
343
- let declarator = declarations[i];
344
- if (isIdentifier(declarator.id)) {
345
- let declaratorPath = exportPath.get(`declaration.declarations.${i}`);
346
- assertNodePathIsVariableDeclarator(declaratorPath), handleExport(declarator.id.name, exportPath, declaratorPath);
347
- continue;
348
- }
349
- if (isPattern(declarator.id)) {
350
- let exportedPatternPath = exportPath.get(`declaration.declarations.${i}.id`);
351
- for (let identifier of (assertNodePathIsPattern(exportedPatternPath), getIdentifiersForPatternPath(exportedPatternPath)))isIdentifier(identifier.node) && handleExport(identifier.node.name, exportPath, identifier);
352
- }
353
- }
354
- return;
355
- }
356
- if (isFunctionDeclaration(declaration) || isClassDeclaration(declaration)) {
357
- invariant(declaration.id, 'Expected exported function or class declaration to have a name when not the default export'), handleExport(declaration.id.name, exportPath);
358
- return;
359
- }
360
- if (isExportNamedDeclaration(node)) {
361
- for (let specifier of node.specifiers)if (isIdentifier(specifier.exported)) {
362
- let name = specifier.exported.name, specifierPath = exportPath.get('specifiers').find((path)=>path.node === specifier);
363
- invariant(specifierPath, `Expected to find specifier path for ${name}`), handleExport(name, exportPath, specifierPath);
364
- }
365
- return;
366
- }
367
- throw Error('Unknown export node type');
368
- }
369
- }), exportDependencies;
370
- }), getDependentIdentifiersForPath = (path, state)=>{
371
- let { visited, identifiers } = state ?? {
372
- visited: new Set(),
373
- identifiers: new Set()
642
+ presets: reactRouterUserConfig.presets ?? [],
643
+ hasConfiguredServerModuleFormat: void 0 !== userAndPresetConfigs.serverModuleFormat
374
644
  };
375
- if (visited.has(path)) return identifiers;
376
- visited.add(path), path.traverse({
377
- Identifier (pathInner) {
378
- if (identifiers.has(pathInner)) return;
379
- identifiers.add(pathInner);
380
- let binding = pathInner.scope.getBinding(pathInner.node.name);
381
- if (binding) {
382
- for (let reference of (getDependentIdentifiersForPath(binding.path, {
383
- visited,
384
- identifiers
385
- }), binding.referencePaths))reference.isExportNamedDeclaration() || getDependentIdentifiersForPath(reference, {
386
- visited,
387
- identifiers
388
- });
389
- for (let constantViolation of binding.constantViolations)getDependentIdentifiersForPath(constantViolation, {
390
- visited,
391
- identifiers
392
- });
393
- }
394
- }
395
- });
396
- let topLevelStatement = getTopLevelStatementPathForPath(path), withinImportStatement = topLevelStatement.isImportDeclaration(), withinExportStatement = topLevelStatement.isExportDeclaration();
397
- if (withinImportStatement || withinExportStatement || getDependentIdentifiersForPath(topLevelStatement, {
398
- visited,
399
- identifiers
400
- }), withinExportStatement && path.isIdentifier() && (isPattern(path.parentPath.node) || isPattern(path.parentPath.parentPath?.node))) {
401
- let variableDeclarator = path.findParent((p)=>p.isVariableDeclarator());
402
- variableDeclarator && (invariant(variableDeclarator && !Array.isArray(variableDeclarator), `Expected a Path, but got ${Array.isArray(variableDeclarator) ? 'an array' : variableDeclarator}`), getDependentIdentifiersForPath(variableDeclarator, {
403
- visited,
404
- identifiers
405
- }));
645
+ }, BROWSER_MANIFEST_ASSET = 'static/js/virtual/react-router/browser-manifest.js', ABSOLUTE_URL_RE = /^[a-zA-Z][a-zA-Z\d+\-.]*:/, addIntegrity = (sri, assetPrefix, assetName, integrity)=>{
646
+ 'string' == typeof assetName && 'string' == typeof integrity && (sri[ABSOLUTE_URL_RE.test(assetName) || assetName.startsWith('//') || assetName.startsWith('/') ? assetName : combineURLs(assetPrefix, assetName)] = integrity);
647
+ };
648
+ function isSourceMapEnabled(value) {
649
+ return !0 === value || !1 !== value && null != value && ('string' == typeof value || 'object' == typeof value && !!value.js);
650
+ }
651
+ function getDevtoolFromRspackConfig(config) {
652
+ if (config && 'function' != typeof config && 'object' == typeof config) return config.devtool;
653
+ }
654
+ function _check_private_redeclaration(obj, privateCollection) {
655
+ if (privateCollection.has(obj)) throw TypeError("Cannot initialize the same private elements twice on an object");
656
+ }
657
+ function _class_extract_field_descriptor(receiver, privateMap, action) {
658
+ if (!privateMap.has(receiver)) throw TypeError("attempted to " + action + " private field on non-instance");
659
+ return privateMap.get(receiver);
660
+ }
661
+ function _class_private_field_get(receiver, privateMap) {
662
+ var descriptor = _class_extract_field_descriptor(receiver, privateMap, "get");
663
+ return descriptor.get ? descriptor.get.call(receiver) : descriptor.value;
664
+ }
665
+ function _class_private_field_init(obj, privateMap, value) {
666
+ _check_private_redeclaration(obj, privateMap), privateMap.set(obj, value);
667
+ }
668
+ function _class_private_field_set(receiver, privateMap, value) {
669
+ var descriptor = _class_extract_field_descriptor(receiver, privateMap, "set");
670
+ if (descriptor.set) descriptor.set.call(receiver, value);
671
+ else {
672
+ if (!descriptor.writable) throw TypeError("attempted to set read only private field");
673
+ descriptor.value = value;
406
674
  }
407
- return identifiers;
408
- }, getTopLevelStatementPathForPath = (path)=>{
409
- let ancestry = path.getAncestry(), topLevelStatement = ancestry[ancestry.length - 2];
410
- return invariant(topLevelStatement && !Array.isArray(topLevelStatement) && isStatement(topLevelStatement.node), `Expected a Statement path, but got ${Array.isArray(topLevelStatement) ? 'an array' : topLevelStatement?.node?.type}`), topLevelStatement;
411
- }, getTopLevelStatementsForPaths = (paths)=>{
412
- let topLevelStatements = new Set();
413
- for (let path of paths){
414
- let topLevelStatement = getTopLevelStatementPathForPath(path);
415
- topLevelStatements.add(topLevelStatement.node);
675
+ return value;
676
+ }
677
+ function _class_private_method_get(receiver, privateSet, fn) {
678
+ if (!privateSet.has(receiver)) throw TypeError("attempted to get private field on non-instance");
679
+ return fn;
680
+ }
681
+ function _class_private_method_init(obj, privateSet) {
682
+ _check_private_redeclaration(obj, privateSet), privateSet.add(obj);
683
+ }
684
+ function _define_property(obj, key, value) {
685
+ return key in obj ? Object.defineProperty(obj, key, {
686
+ value: value,
687
+ enumerable: !0,
688
+ configurable: !0,
689
+ writable: !0
690
+ }) : obj[key] = value, obj;
691
+ }
692
+ class WorkerStartupError extends Error {
693
+ constructor(message){
694
+ super(message), this.name = 'WorkerStartupError';
416
695
  }
417
- return topLevelStatements;
418
- }, getIdentifiersForPatternPath = (patternPath, identifiers = new Set())=>(!function walk(currentPath) {
419
- if (currentPath.isIdentifier()) return void identifiers.add(currentPath);
420
- if (currentPath.isObjectPattern()) {
421
- let { properties } = currentPath.node;
422
- for(let i = 0; i < properties.length; i++){
423
- let property = properties[i];
424
- if (isObjectProperty(property)) {
425
- let valuePath = currentPath.get(`properties.${i}.value`);
426
- isNodePathWithNode(valuePath) && walk(valuePath);
427
- } else if (isRestElement(property)) {
428
- let argumentPath = currentPath.get(`properties.${i}.argument`);
429
- isNodePathWithNode(argumentPath) && walk(argumentPath);
430
- }
431
- }
432
- } else if (currentPath.isArrayPattern()) {
433
- let { elements } = currentPath.node;
434
- for(let i = 0; i < elements.length; i++)if (elements[i]) {
435
- let elementPath = currentPath.get(`elements.${i}`);
436
- isNodePathWithNode(elementPath) && walk(elementPath);
437
- }
438
- } else if (currentPath.isRestElement()) {
439
- let argumentPath = currentPath.get('argument');
440
- isNodePathWithNode(argumentPath) && walk(argumentPath);
441
- }
442
- }(patternPath), identifiers), getExportedName = (exported)=>isIdentifier(exported) ? exported.name : exported.value, setsIntersect = (set1, set2)=>{
443
- let smallerSet = set1, largerSet = set2;
444
- for (let element of (set1.size > set2.size && (smallerSet = set2, largerSet = set1), smallerSet))if (largerSet.has(element)) return !0;
445
- return !1;
446
- }, hasChunkableExport = (code, exportName, cache, cacheKey)=>getOrSetFromCache(cache, `${cacheKey}::hasChunkableExport::${exportName}`, code, ()=>{
447
- let exportDependencies = getExportDependencies(code, cache, cacheKey), dependencies = exportDependencies.get(exportName);
448
- if (!dependencies) return !1;
449
- for (let [currentExportName, currentDependencies] of exportDependencies)if (currentExportName !== exportName && setsIntersect(currentDependencies.topLevelNonModuleStatements, dependencies.topLevelNonModuleStatements)) return !1;
450
- if (dependencies.exportedVariableDeclarators.size > 1) return !1;
451
- if (dependencies.exportedVariableDeclarators.size > 0) {
452
- for (let [currentExportName, currentDependencies] of exportDependencies)if (currentExportName !== exportName && setsIntersect(currentDependencies.exportedVariableDeclarators, dependencies.exportedVariableDeclarators)) return !1;
696
+ }
697
+ var _closed = new WeakMap(), _closePromise = new WeakMap(), _workersDisabled = new WeakMap(), _nextId = new WeakMap(), _nextRouteModuleWorkerIndex = new WeakMap(), _nextSplitRouteAnalysisWorkerIndex = new WeakMap(), _splitRouteAnalysisWorkers = new WeakMap(), _workers = new WeakMap(), _disableWorkers = new WeakSet(), _createWorkerState = new WeakSet(), _runInWorker = new WeakSet(), _createWorkerRequestTask = new WeakSet(), _getWorkerIndex = new WeakSet();
698
+ class ParallelRouteTransformExecutor {
699
+ async run(task) {
700
+ if (_class_private_field_get(this, _closed) || 'clientOnlyStub' === task.kind && task.resolveExportAllModule) return executeRouteTransformTask(task, this.options);
701
+ try {
702
+ return await _class_private_method_get(this, _runInWorker, runInWorker).call(this, task);
703
+ } catch (error) {
704
+ if (error instanceof WorkerStartupError) return executeRouteTransformTask(task, this.options);
705
+ throw error;
453
706
  }
454
- return !0;
455
- }), getRouteChunkModuleId = (filePath, chunkName)=>`${filePath}${routeChunkQueryStrings[chunkName]}`, normalizeRelativeFilePath = (file, appDirectory)=>{
456
- let fullPath = resolve(appDirectory, file);
457
- return normalize(relative(appDirectory, fullPath)).split('?')[0];
458
- }, isRootRouteModuleId = (config, id)=>normalizeRelativeFilePath(id, config.appDirectory) === config.rootRouteFile, detectRouteChunksIfEnabled = async (cache, config, id, code)=>{
459
- let hasRouteChunkByExportName, chunkedExports;
460
- if (!config.splitRouteModules || isRootRouteModuleId(config, id) || !routeChunkExportNames.some((exportName)=>code.includes(exportName))) return {
461
- chunkedExports: [],
462
- hasRouteChunks: !1,
463
- hasRouteChunkByExportName: {
464
- clientAction: !1,
465
- clientLoader: !1,
466
- clientMiddleware: !1,
467
- HydrateFallback: !1
707
+ }
708
+ close() {
709
+ if (_class_private_field_get(this, _closePromise)) return _class_private_field_get(this, _closePromise);
710
+ _class_private_field_set(this, _closed, !0);
711
+ let workers = _class_private_field_get(this, _workers);
712
+ return _class_private_field_set(this, _workers, []), _class_private_field_set(this, _closePromise, Promise.all(workers.map(async (state)=>{
713
+ for (let pending of state.pending.values())pending.reject(Error('Route transform worker closed.'));
714
+ state.pending.clear(), await state.worker.terminate();
715
+ })).then(()=>void 0)), _class_private_field_get(this, _closePromise);
716
+ }
717
+ constructor(workerCount, options, balanceRouteModuleTransforms){
718
+ _class_private_method_init(this, _disableWorkers), _class_private_method_init(this, _createWorkerState), _class_private_method_init(this, _runInWorker), _class_private_method_init(this, _createWorkerRequestTask), _class_private_method_init(this, _getWorkerIndex), _define_property(this, "options", void 0), _define_property(this, "balanceRouteModuleTransforms", void 0), _class_private_field_init(this, _closed, {
719
+ writable: !0,
720
+ value: void 0
721
+ }), _class_private_field_init(this, _closePromise, {
722
+ writable: !0,
723
+ value: void 0
724
+ }), _class_private_field_init(this, _workersDisabled, {
725
+ writable: !0,
726
+ value: void 0
727
+ }), _class_private_field_init(this, _nextId, {
728
+ writable: !0,
729
+ value: void 0
730
+ }), _class_private_field_init(this, _nextRouteModuleWorkerIndex, {
731
+ writable: !0,
732
+ value: void 0
733
+ }), _class_private_field_init(this, _nextSplitRouteAnalysisWorkerIndex, {
734
+ writable: !0,
735
+ value: void 0
736
+ }), _class_private_field_init(this, _splitRouteAnalysisWorkers, {
737
+ writable: !0,
738
+ value: void 0
739
+ }), _class_private_field_init(this, _workers, {
740
+ writable: !0,
741
+ value: void 0
742
+ }), this.options = options, this.balanceRouteModuleTransforms = balanceRouteModuleTransforms, _class_private_field_set(this, _closed, !1), _class_private_field_set(this, _workersDisabled, !1), _class_private_field_set(this, _nextId, 1), _class_private_field_set(this, _nextRouteModuleWorkerIndex, 0), _class_private_field_set(this, _nextSplitRouteAnalysisWorkerIndex, 0), _class_private_field_set(this, _splitRouteAnalysisWorkers, new Map()), _class_private_field_set(this, _workers, []);
743
+ try {
744
+ for(let index = 0; index < workerCount; index += 1)_class_private_field_get(this, _workers).push(_class_private_method_get(this, _createWorkerState, createWorkerState).call(this));
745
+ } catch (error) {
746
+ for (let state of _class_private_field_get(this, _workers))state.worker.terminate();
747
+ throw _class_private_field_set(this, _workers, []), error;
468
748
  }
749
+ }
750
+ }
751
+ function disableWorkers(error) {
752
+ if (_class_private_field_get(this, _workersDisabled) || _class_private_field_get(this, _closed)) return;
753
+ _class_private_field_set(this, _workersDisabled, !0);
754
+ let workers = _class_private_field_get(this, _workers);
755
+ for (let state of (_class_private_field_set(this, _workers, []), workers)){
756
+ for (let pending of state.pending.values())pending.reject(error);
757
+ state.pending.clear(), state.worker.terminate();
758
+ }
759
+ }
760
+ function createWorkerState() {
761
+ let worker = new Worker(new URL('./parallel-route-transform-worker.js', import.meta.url)), state = {
762
+ worker,
763
+ pending: new Map(),
764
+ sourceCache: new Map()
469
765
  };
470
- let cacheKey = normalizeRelativeFilePath(id, config.appDirectory);
471
- return {
472
- hasRouteChunks: (chunkedExports = Object.entries(hasRouteChunkByExportName = Object.fromEntries(routeChunkExportNames.map((exportName)=>[
473
- exportName,
474
- hasChunkableExport(code, exportName, cache, cacheKey)
475
- ]))).filter(([, isChunked])=>isChunked).map(([exportName])=>exportName)).length > 0,
476
- hasRouteChunkByExportName,
477
- chunkedExports
478
- };
479
- }, getRouteChunkIfEnabled = async (cache, config, id, chunkName, code)=>{
480
- if (!config.splitRouteModules) return null;
481
- let cacheKey = normalizeRelativeFilePath(id, config.appDirectory);
482
- return ('main' === chunkName ? ((code, exportNames, generateOptions = {}, cache, cacheKey)=>getOrSetFromCache(cache, `${cacheKey}::omitChunkedExports::${exportNames.join(',')}::${JSON.stringify(generateOptions)}`, code, ()=>{
483
- let isOmitted = (exportName)=>exportNames.includes(exportName) && hasChunkableExport(code, exportName, cache, cacheKey), exportDependencies = getExportDependencies(code, cache, cacheKey), allExportNames = Array.from(exportDependencies.keys()), omittedExportNames = allExportNames.filter(isOmitted), retainedExportNames = allExportNames.filter((exportName)=>!isOmitted(exportName)), omittedStatements = new Set(), omittedExportedVariableDeclarators = new Set();
484
- for (let omittedExportName of omittedExportNames){
485
- let dependencies = exportDependencies.get(omittedExportName);
486
- for (let statement of (invariant(dependencies, `Expected dependencies for ${omittedExportName}`), dependencies.topLevelNonModuleStatements))omittedStatements.add(statement);
487
- for (let declarator of dependencies.exportedVariableDeclarators)omittedExportedVariableDeclarators.add(declarator);
488
- }
489
- let ast = codeToAst(code, cache, cacheKey), omittedStatementsArray = Array.from(omittedStatements), omittedExportedVariableDeclaratorsArray = Array.from(omittedExportedVariableDeclarators);
490
- if (ast.program.body = ast.program.body.filter((node)=>omittedStatementsArray.every((statement)=>!isNodesEquivalent(node, statement))).map((node)=>isImportDeclaration(node) && 0 !== node.specifiers.length && (node.specifiers = node.specifiers.filter((specifier)=>{
491
- let importedName = specifier.local.name;
492
- for (let retainedExportName of retainedExportNames){
493
- let dependencies = exportDependencies.get(retainedExportName);
494
- if (dependencies?.importedIdentifierNames?.has(importedName)) return !0;
495
- }
496
- for (let omittedExportName of omittedExportNames){
497
- let dependencies = exportDependencies.get(omittedExportName);
498
- if (dependencies?.importedIdentifierNames?.has(importedName)) return !1;
499
- }
500
- return !0;
501
- }), 0 === node.specifiers.length) ? null : node).map((node)=>{
502
- if (!isExportDeclaration(node) || isExportAllDeclaration(node)) return node;
503
- if (isExportDefaultDeclaration(node)) return isOmitted('default') ? null : node;
504
- if (isVariableDeclaration(node.declaration)) return (node.declaration.declarations = node.declaration.declarations.filter((declarationNode)=>omittedExportedVariableDeclaratorsArray.every((declarator)=>!isNodesEquivalent(declarationNode, declarator))), 0 === node.declaration.declarations.length) ? null : node;
505
- if (isFunctionDeclaration(node.declaration) || isClassDeclaration(node.declaration)) {
506
- let declarationId = node.declaration.id;
507
- return invariant(declarationId, 'Expected exported function or class declaration to have a name when not the default export'), isOmitted(declarationId.name) ? null : node;
766
+ return worker.on('message', (response)=>{
767
+ let pending = state.pending.get(response.id);
768
+ if (pending) if (state.pending.delete(response.id), response.ok) pending.resolve(response.result);
769
+ else {
770
+ var error;
771
+ let result;
772
+ pending.reject(((result = Error((error = response.error).message)).name = error.name ?? 'Error', error.stack && (result.stack = error.stack), result));
773
+ }
774
+ }), worker.on('error', (error)=>{
775
+ let startupError = new WorkerStartupError(error.message);
776
+ startupError.stack = error.stack, _class_private_method_get(this, _disableWorkers, disableWorkers).call(this, startupError);
777
+ }), worker.on('exit', (code)=>{
778
+ if (_class_private_field_get(this, _closed) || _class_private_field_get(this, _workersDisabled)) return;
779
+ let startupError = new WorkerStartupError(`Route transform worker exited with code ${code}.`);
780
+ _class_private_method_get(this, _disableWorkers, disableWorkers).call(this, startupError);
781
+ }), state;
782
+ }
783
+ function runInWorker(task) {
784
+ let workerIndex = _class_private_method_get(this, _getWorkerIndex, getWorkerIndex).call(this, task), state = _class_private_field_get(this, _workers)[workerIndex];
785
+ if (!state) return executeRouteTransformTask(task, this.options);
786
+ let id = function(receiver, privateMap) {
787
+ var descriptor = _class_extract_field_descriptor(receiver, privateMap, "update");
788
+ if (descriptor.set) {
789
+ if (!descriptor.get) throw TypeError("attempted to read set only private field");
790
+ return "__destrWrapper" in descriptor || (descriptor.__destrWrapper = {
791
+ set value (v){
792
+ descriptor.set.call(receiver, v);
793
+ },
794
+ get value () {
795
+ return descriptor.get.call(receiver);
508
796
  }
509
- if (isExportNamedDeclaration(node)) return 0 === node.specifiers.length ? node : (node.specifiers = node.specifiers.filter((specifier)=>!isOmitted(getExportedName(specifier.exported))), 0 === node.specifiers.length) ? null : node;
510
- throw Error('Unknown node type');
511
- }).filter(Boolean), 0 !== ast.program.body.length) return generate(ast, generateOptions).code;
512
- }))(code, routeChunkExportNames, {}, cache, cacheKey) : ((code, exportName, generateOptions = {}, cache, cacheKey)=>getOrSetFromCache(cache, `${cacheKey}::getChunkedExport::${exportName}::${JSON.stringify(generateOptions)}`, code, ()=>{
513
- if (!hasChunkableExport(code, exportName, cache, cacheKey)) return;
514
- let dependencies = getExportDependencies(code, cache, cacheKey).get(exportName);
515
- invariant(dependencies, 'Expected export to have dependencies');
516
- let topLevelStatementsArray = Array.from(dependencies.topLevelStatements), exportedVariableDeclaratorsArray = Array.from(dependencies.exportedVariableDeclarators), ast = codeToAst(code, cache, cacheKey);
517
- return ast.program.body = ast.program.body.filter((node)=>topLevelStatementsArray.some((statement)=>isNodesEquivalent(node, statement))).map((node)=>isImportDeclaration(node) ? 0 === dependencies.importedIdentifierNames.size ? null : (node.specifiers = node.specifiers.filter((specifier)=>dependencies.importedIdentifierNames.has(specifier.local.name)), invariant(node.specifiers.length > 0, 'Expected import statement to have used specifiers'), node) : node).map((node)=>{
518
- if (!isExportDeclaration(node)) return node;
519
- if (isExportAllDeclaration(node)) return null;
520
- if (isExportDefaultDeclaration(node)) return 'default' === exportName ? node : null;
521
- let { declaration } = node;
522
- if (isVariableDeclaration(declaration)) return (declaration.declarations = declaration.declarations.filter((declarationNode)=>exportedVariableDeclaratorsArray.some((declarator)=>isNodesEquivalent(declarationNode, declarator))), 0 === declaration.declarations.length) ? null : node;
523
- if (isFunctionDeclaration(node.declaration) || isClassDeclaration(node.declaration)) return node.declaration.id?.name === exportName ? node : null;
524
- if (isExportNamedDeclaration(node)) return 0 === node.specifiers.length || (node.specifiers = node.specifiers.filter((specifier)=>getExportedName(specifier.exported) === exportName), 0 === node.specifiers.length) ? null : node;
525
- throw Error('Unknown export node type');
526
- }).filter(Boolean), generate(ast, generateOptions).code;
527
- }))(code, chunkName, {}, cache, cacheKey)) ?? null;
528
- }, validateRouteChunks = ({ config, id, valid })=>{
529
- if (isRootRouteModuleId(config, id)) return;
530
- let invalidChunks = Object.entries(valid).filter(([, isValid])=>!isValid).map(([chunkName])=>chunkName);
531
- if (0 === invalidChunks.length) return;
532
- let plural = invalidChunks.length > 1;
533
- throw Error([
534
- `Error splitting route module: ${normalizeRelativeFilePath(id, config.appDirectory)}`,
535
- invalidChunks.map((name)=>`- ${name}`).join('\n'),
536
- `${plural ? 'These exports' : 'This export'} could not be split into ${plural ? 'their own chunks' : 'its own chunk'} because ${plural ? 'they share' : 'it shares'} code with other exports. You should extract any shared code into its own module and then import it within the route module.`
537
- ].join('\n\n'));
538
- }, getRouteChunkEntryName = (routeId, chunkName)=>`${routeId}-${routeChunkEntrySuffix[chunkName]}`;
539
- (A = ImportType || (ImportType = {}))[A.Static = 1] = "Static", A[A.Dynamic = 2] = "Dynamic", A[A.ImportMeta = 3] = "ImportMeta", A[A.StaticSourcePhase = 4] = "StaticSourcePhase", A[A.DynamicSourcePhase = 5] = "DynamicSourcePhase", A[A.StaticDeferPhase = 6] = "StaticDeferPhase", A[A.DynamicDeferPhase = 7] = "DynamicDeferPhase";
540
- let lexer_A = 1 === new Uint8Array(new Uint16Array([
541
- 1
542
- ]).buffer)[0];
543
- function lexer_parse(E, g = "@") {
544
- if (!lexer_C) return lexer_init.then(()=>lexer_parse(E));
545
- let I = E.length + 1, w = (lexer_C.__heap_base.value || lexer_C.__heap_base) + 4 * I - lexer_C.memory.buffer.byteLength;
546
- w > 0 && lexer_C.memory.grow(Math.ceil(w / 65536));
547
- let K = lexer_C.sa(I - 1);
548
- if ((lexer_A ? function(A, Q) {
549
- let B = A.length, C = 0;
550
- for(; C < B;)Q[C] = A.charCodeAt(C++);
551
- } : function(A, Q) {
552
- let B = A.length, C = 0;
553
- for(; C < B;){
554
- let B = A.charCodeAt(C);
555
- Q[C++] = (255 & B) << 8 | B >>> 8;
797
+ }), descriptor.__destrWrapper;
556
798
  }
557
- })(E, new Uint16Array(lexer_C.memory.buffer, K, I)), !lexer_C.parse()) throw Object.assign(Error(`Parse error ${g}:${E.slice(0, lexer_C.e()).split("\n").length}:${lexer_C.e() - E.lastIndexOf("\n", lexer_C.e() - 1)}`), {
558
- idx: lexer_C.e()
559
- });
560
- let o = [], D = [];
561
- for(; lexer_C.ri();){
562
- let D, A = lexer_C.is(), Q = lexer_C.ie(), B = lexer_C.it(), g = lexer_C.ai(), I = lexer_C.id(), w = lexer_C.ss(), K = lexer_C.se();
563
- lexer_C.ip() && (D = k(E.slice(-1 === I ? A - 1 : A, -1 === I ? Q + 1 : Q))), o.push({
564
- n: D,
565
- t: B,
566
- s: A,
567
- e: Q,
568
- ss: w,
569
- se: K,
570
- d: I,
571
- a: g
799
+ if (!descriptor.writable) throw TypeError("attempted to set read only private field");
800
+ return descriptor;
801
+ }(this, _nextId).value++, sourceCacheKey = task.resourcePath, requestTask = _class_private_method_get(this, _createWorkerRequestTask, createWorkerRequestTask).call(this, state, task, sourceCacheKey);
802
+ return new Promise((resolve, reject)=>{
803
+ state.pending.set(id, {
804
+ resolve,
805
+ reject
572
806
  });
807
+ try {
808
+ state.worker.postMessage({
809
+ id,
810
+ task: requestTask,
811
+ sourceCacheKey
812
+ });
813
+ } catch (error) {
814
+ state.pending.delete(id), state.sourceCache.delete(sourceCacheKey), reject(error instanceof Error ? error : Error(String(error)));
815
+ }
816
+ });
817
+ }
818
+ function createWorkerRequestTask(state, task, sourceCacheKey) {
819
+ if (state.sourceCache.get(sourceCacheKey) === task.code) {
820
+ let { code: _code, ...cachedTask } = task;
821
+ return cachedTask;
573
822
  }
574
- for(; lexer_C.re();){
575
- let A = lexer_C.es(), Q = lexer_C.ee(), B = lexer_C.els(), g = lexer_C.ele(), I = E.slice(A, Q), w = I[0], K = B < 0 ? void 0 : E.slice(B, g), o = K ? K[0] : "";
576
- D.push({
577
- s: A,
578
- e: Q,
579
- ls: B,
580
- le: g,
581
- n: '"' === w || "'" === w ? k(I) : I,
582
- ln: '"' === o || "'" === o ? k(K) : K
583
- });
823
+ return setBoundedCacheEntry(state.sourceCache, sourceCacheKey, task.code, 2048), task;
824
+ }
825
+ function getWorkerIndex(task) {
826
+ let workerCount = Math.max(1, _class_private_field_get(this, _workers).length);
827
+ if (this.balanceRouteModuleTransforms && ('routeClientEntry' === task.kind || 'routeChunk' === task.kind || 'splitRouteExports' === task.kind)) {
828
+ let existingWorkerIndex = _class_private_field_get(this, _splitRouteAnalysisWorkers).get(task.resourcePath);
829
+ if (void 0 !== existingWorkerIndex) return existingWorkerIndex % workerCount;
830
+ let workerIndex = _class_private_field_get(this, _nextSplitRouteAnalysisWorkerIndex) % workerCount;
831
+ return _class_private_field_set(this, _nextSplitRouteAnalysisWorkerIndex, _class_private_field_get(this, _nextSplitRouteAnalysisWorkerIndex) + 1), _class_private_field_get(this, _splitRouteAnalysisWorkers).set(task.resourcePath, workerIndex), workerIndex;
584
832
  }
585
- function k(A) {
586
- try {
587
- return (0, eval)(A);
588
- } catch (A) {}
833
+ if (this.balanceRouteModuleTransforms && 'routeModule' === task.kind && !('web' === task.environmentName && !task.ssr && task.isSpaMode)) {
834
+ let workerIndex = _class_private_field_get(this, _nextRouteModuleWorkerIndex) % workerCount;
835
+ return _class_private_field_set(this, _nextRouteModuleWorkerIndex, _class_private_field_get(this, _nextRouteModuleWorkerIndex) + 1), workerIndex;
589
836
  }
590
- return [
591
- o,
592
- D,
593
- !!lexer_C.f(),
594
- !!lexer_C.ms()
595
- ];
837
+ return ((value)=>{
838
+ let hash = 0;
839
+ for(let index = 0; index < value.length; index += 1)hash = 31 * hash + value.charCodeAt(index) >>> 0;
840
+ return hash;
841
+ })(task.resourcePath) % workerCount;
596
842
  }
597
- let lexer_init = WebAssembly.compile((A1 = "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GzYCHAtBAEEAKAKwCkECajYCsAoCQAJAAkACQEEAECkiAUHhAEYNACABQfcARg0BQQAoArAKIQEMAgtBACgCsAoiAUECakHACEEKEC8NAUEGIQIMAgtBACgCsAoiAS8BAkHpAEcNACABLwEEQfQARw0AQQQhAiABLwEGQegARg0BC0EAIAFBfmo2ArAKDwtBACABIAJBAXRqNgKwCgJAQQEQKUH7AEYNAEEAIAE2ArAKDwtBACgCsAoiACECA0BBACACQQJqNgKwCgJAAkACQEEBECkiAkEiRg0AIAJBJ0cNAUEnEBpBAEEAKAKwCkECajYCsApBARApIQIMAgtBIhAaQQBBACgCsApBAmo2ArAKQQEQKSECDAELIAIQLCECCwJAIAJBOkYNAEEAIAE2ArAKDwtBAEEAKAKwCkECajYCsAoCQEEBECkiAkEiRg0AIAJBJ0YNAEEAIAE2ArAKDwsgAhAaQQBBACgCsApBAmo2ArAKAkACQEEBECkiAkEsRg0AIAJB/QBGDQFBACABNgKwCg8LQQBBACgCsApBAmo2ArAKQQEQKUH9AEYNAEEAKAKwCiECDAELC0EAKALwCSIBIAA2AhAgAUEAKAKwCkECajYCDAttAQJ/AkACQANAAkAgAEH//wNxIgFBd2oiAkEXSw0AQQEgAnRBn4CABHENAgsgAUGgAUYNASAAIQIgARAoDQJBACECQQBBACgCsAoiAEECajYCsAogAC8BAiIADQAMAgsLIAAhAgsgAkH//wNxC6sBAQR/AkACQEEAKAKwCiICLwEAIgNB4QBGDQAgASEEIAAhBQwBC0EAIAJBBGo2ArAKQQEQKSECQQAoArAKIQUCQAJAIAJBIkYNACACQSdGDQAgAhAsGkEAKAKwCiEEDAELIAIQGkEAQQAoArAKQQJqIgQ2ArAKC0EBECkhA0EAKAKwCiECCwJAIAIgBUYNACAFIARBACAAIAAgAUYiAhtBACABIAIbEAILIAMLcgEEf0EAKAKwCiEAQQAoArQKIQECQAJAA0AgAEECaiECIAAgAU8NAQJAAkAgAi8BACIDQaR/ag4CAQQACyACIQAgA0F2ag4EAgEBAgELIABBBGohAAwACwtBACACNgKwChAlQQAPC0EAIAI2ArAKQd0AC0kBA39BACEDAkAgAkUNAAJAA0AgAC0AACIEIAEtAAAiBUcNASABQQFqIQEgAEEBaiEAIAJBf2oiAg0ADAILCyAEIAVrIQMLIAMLC+wBAgBBgAgLzgEAAHgAcABvAHIAdABtAHAAbwByAHQAZgBvAHIAZQB0AGEAbwB1AHIAYwBlAHIAbwBtAHUAbgBjAHQAaQBvAG4AcwBzAGUAcgB0AHYAbwB5AGkAZQBkAGUAbABlAGMAbwBuAHQAaQBuAGkAbgBzAHQAYQBuAHQAeQBiAHIAZQBhAHIAZQB0AHUAcgBkAGUAYgB1AGcAZwBlAGEAdwBhAGkAdABoAHIAdwBoAGkAbABlAGkAZgBjAGEAdABjAGYAaQBuAGEAbABsAGUAbABzAABB0AkLEAEAAAACAAAAAAQAAEA5AAA=", "u" > typeof Buffer ? Buffer.from(A1, "base64") : Uint8Array.from(atob(A1), (A)=>A.charCodeAt(0)))).then(WebAssembly.instantiate).then(({ exports: A })=>{
598
- lexer_C = A;
599
- }), transformToEsm = async (code, resourcePath)=>(await __rspack_external_esbuild.transform(code, {
600
- jsx: 'automatic',
601
- format: 'esm',
602
- platform: 'neutral',
603
- loader: JS_LOADERS[extname(resourcePath)] ?? 'js'
604
- })).code, getExportNames = async (code)=>{
605
- await lexer_init;
606
- let [, exportSpecifiers] = await lexer_parse(code);
607
- return Array.from(new Set(exportSpecifiers.map((specifier)=>specifier.n).filter(Boolean)));
608
- }, getExportNamesAndExportAll = async (code)=>{
609
- await lexer_init;
610
- let [imports, exportSpecifiers] = await lexer_parse(code), exportNames = new Set();
611
- for (let specifier of exportSpecifiers)specifier.n && exportNames.add(specifier.n);
612
- let exportAllModules = [];
613
- for (let entry of imports){
614
- if (!entry.n) continue;
615
- let statement = code.slice(entry.ss, entry.se);
616
- /^\s*export\s*\*\s*from\s*['"]/.test(statement) && exportAllModules.push(entry.n);
843
+ let defaultWatchDirectoryEntry = (directory, onChange, onError)=>{
844
+ let watcher = watch(directory, onChange);
845
+ return watcher.on('error', onError), watcher;
846
+ }, ensureDevRestartMarker = async (restartMarkerPath)=>{
847
+ await mkdir(dirname(restartMarkerPath), {
848
+ recursive: !0
849
+ });
850
+ try {
851
+ await access(restartMarkerPath);
852
+ } catch {
853
+ await writeFile(restartMarkerPath, 'react-router-route-watch');
617
854
  }
618
- return {
619
- exportNames: Array.from(exportNames),
620
- exportAllModules
621
- };
622
- }, getRouteModuleExports = async (resourcePath)=>{
623
- let source = await readFile(resourcePath, 'utf8');
624
- return getExportNames(await transformToEsm(source, resourcePath));
625
- }, DEFAULT_MANIFEST_DIR = 'static/js', getReactRouterManifestPath = ({ version, isBuild, entryModulePath })=>{
626
- if (!isBuild) return 'static/js/virtual/react-router/browser-manifest.js';
627
- let dir = ((entryModulePath)=>{
628
- if (!entryModulePath) return DEFAULT_MANIFEST_DIR;
629
- let dir = dirname(entryModulePath);
630
- return '.' === dir ? DEFAULT_MANIFEST_DIR : dir;
631
- })(entryModulePath);
632
- return `${dir}/manifest-${version}.js`;
633
- }, getRouteEntryName = (route)=>{
634
- let extensionIndex = route.file.lastIndexOf('.');
635
- return extensionIndex >= 0 ? route.file.slice(0, extensionIndex) : route.file;
636
- };
637
- async function getReactRouterManifestForDev(routes, options, clientStats, context, assetPrefix = '/', routeChunkOptions) {
638
- let result = {}, splitRouteModules = routeChunkOptions?.splitRouteModules ?? !1, enforceSplitRouteModules = 'enforce' === splitRouteModules, isBuild = routeChunkOptions?.isBuild ?? !1, routeChunkConfig = splitRouteModules && routeChunkOptions?.rootRouteFile ? {
639
- splitRouteModules,
640
- appDirectory: context,
641
- rootRouteFile: routeChunkOptions.rootRouteFile
642
- } : null, getAssetsForChunk = (chunkName)=>{
643
- let assets = clientStats?.assetsByChunkName?.[chunkName];
644
- if (!assets) return [
645
- `${DEFAULT_MANIFEST_DIR}/${chunkName}.js`
646
- ];
647
- let normalizedAssets = Array.isArray(assets) ? assets : [
648
- assets
649
- ];
650
- return normalizedAssets.some((asset)=>asset.endsWith('.js')) ? normalizedAssets : [
651
- `${DEFAULT_MANIFEST_DIR}/${chunkName}.js`,
652
- ...normalizedAssets
653
- ];
654
- }, getModulePathForChunk = (chunkName)=>{
655
- let jsAssets = getAssetsForChunk(chunkName).filter((asset)=>asset.endsWith('.js'));
656
- return jsAssets[0] ? combineURLs(assetPrefix, jsAssets[0]) : void 0;
855
+ }, readRouteDirectories = async (watchDirectory)=>{
856
+ let directories = new Set(), walkDirectory = async (directory)=>{
857
+ let entries;
858
+ try {
859
+ entries = await readdir(directory, {
860
+ withFileTypes: !0
861
+ });
862
+ } catch {
863
+ return;
864
+ }
865
+ directories.add(directory), await Promise.all(entries.map(async (entry)=>{
866
+ let entryPath = external_pathe_resolve(directory, entry.name);
867
+ entry.isDirectory() && await walkDirectory(entryPath);
868
+ }));
657
869
  };
658
- for (let [key, route] of Object.entries(routes)){
659
- let routeEntryName = getRouteEntryName(route), assets = getAssetsForChunk(routeEntryName), jsAssets = assets.filter((asset)=>asset.endsWith('.js')) || [], cssAssets = assets.filter((asset)=>asset.endsWith('.css')) || [], routeFilePath = resolve(context, route.file), exports = new Set(), hasRouteChunkByExportName = {
660
- clientAction: !1,
661
- clientLoader: !1,
662
- clientMiddleware: !1,
663
- HydrateFallback: !1
870
+ return await walkDirectory(watchDirectory), directories;
871
+ }, createRouteTopologyWatcher = async ({ watchDirectory, getRouteTopology, initialRouteTopology, restartMarkerPath, onError, onRouteTopologyChange, watchDirectoryEntry: watchDirectoryOverride = defaultWatchDirectoryEntry })=>{
872
+ let discoveredState, rescanTimer, discoveredDirectories = await readRouteDirectories(watchDirectory);
873
+ try {
874
+ discoveredState = {
875
+ directories: discoveredDirectories,
876
+ routeTopology: await getRouteTopology()
664
877
  };
665
- try {
666
- let source = await readFile(routeFilePath, 'utf8');
667
- !isBuild && 0 === cssAssets.length && /\.(?:css|less|sass|scss)(?:\?[^'"`]+)?['"`]/.test(source) && (cssAssets = [
668
- `${DEFAULT_MANIFEST_DIR.replace('/js', '/css')}/${routeEntryName}.css`
669
- ]);
670
- let code = await transformToEsm(source, routeFilePath);
671
- if (exports = new Set(await getExportNames(code)), isBuild && routeChunkConfig) {
672
- let { hasRouteChunkByExportName: chunkInfo } = await detectRouteChunksIfEnabled(routeChunkOptions?.cache, routeChunkConfig, routeFilePath, code);
673
- hasRouteChunkByExportName = chunkInfo;
674
- }
878
+ } catch (error) {
879
+ if (!initialRouteTopology) throw error;
880
+ onError(error), discoveredState = {
881
+ directories: discoveredDirectories,
882
+ routeTopology: initialRouteTopology
883
+ };
884
+ }
885
+ let state = {
886
+ ...discoveredState,
887
+ routeTopology: initialRouteTopology ?? discoveredState.routeTopology
888
+ }, closed = !1, rescanQueue = Promise.resolve(), directoryWatchers = new Map(), touchRestartMarker = async ()=>{
889
+ await mkdir(dirname(restartMarkerPath), {
890
+ recursive: !0
891
+ }), await writeFile(restartMarkerPath, String(Date.now()));
892
+ }, syncDirectoryWatchers = (nextDirectories)=>{
893
+ for (let [directory, watcher] of directoryWatchers)nextDirectories.has(directory) || (watcher.close(), directoryWatchers.delete(directory));
894
+ for (let directory of nextDirectories)if (!directoryWatchers.has(directory)) try {
895
+ let watcher;
896
+ watcher = watchDirectoryOverride(directory, scheduleRescan, (error)=>{
897
+ directoryWatchers.get(directory) === watcher && (watcher.close(), directoryWatchers.delete(directory)), onError(error);
898
+ }), directoryWatchers.set(directory, watcher);
675
899
  } catch (error) {
676
- console.error(`Failed to analyze route file ${routeFilePath}:`, error);
900
+ onError(error);
677
901
  }
678
- let hasClientAction = exports.has('clientAction'), hasClientLoader = exports.has('clientLoader'), hasClientMiddleware = exports.has('clientMiddleware'), hasHydrateFallback = exports.has('HydrateFallback'), hasDefaultExport = exports.has('default');
679
- isBuild && enforceSplitRouteModules && routeChunkConfig && validateRouteChunks({
680
- config: routeChunkConfig,
681
- id: routeFilePath,
682
- valid: {
683
- clientAction: !hasClientAction || hasRouteChunkByExportName.clientAction,
684
- clientLoader: !hasClientLoader || hasRouteChunkByExportName.clientLoader,
685
- clientMiddleware: !hasClientMiddleware || hasRouteChunkByExportName.clientMiddleware,
686
- HydrateFallback: !hasHydrateFallback || hasRouteChunkByExportName.HydrateFallback
902
+ }, applyNextState = async (nextState)=>{
903
+ if (!closed) {
904
+ if (syncDirectoryWatchers(nextState.directories), !((left, right)=>{
905
+ if (left.size !== right.size) return !1;
906
+ for (let value of left)if (!right.has(value)) return !1;
907
+ return !0;
908
+ })(state.routeTopology, nextState.routeTopology)) {
909
+ if (onRouteTopologyChange) {
910
+ state = nextState;
911
+ try {
912
+ Promise.resolve(onRouteTopologyChange()).catch(onError);
913
+ } catch (error) {
914
+ onError(error);
915
+ }
916
+ return;
917
+ }
918
+ if (await touchRestartMarker(), closed) return;
919
+ state = nextState;
920
+ return;
687
921
  }
688
- }), result[key] = {
689
- id: route.id,
690
- parentId: route.parentId,
691
- path: route.path,
692
- index: route.index,
693
- caseSensitive: route.caseSensitive,
694
- module: combineURLs(assetPrefix, jsAssets[0] || ''),
695
- clientActionModule: isBuild && hasRouteChunkByExportName.clientAction ? getModulePathForChunk(getRouteChunkEntryName(route.id, 'clientAction')) : void 0,
696
- clientLoaderModule: isBuild && hasRouteChunkByExportName.clientLoader ? getModulePathForChunk(getRouteChunkEntryName(route.id, 'clientLoader')) : void 0,
697
- clientMiddlewareModule: isBuild && hasRouteChunkByExportName.clientMiddleware ? getModulePathForChunk(getRouteChunkEntryName(route.id, 'clientMiddleware')) : void 0,
698
- hydrateFallbackModule: isBuild && hasRouteChunkByExportName.HydrateFallback ? getModulePathForChunk(getRouteChunkEntryName(route.id, 'HydrateFallback')) : void 0,
699
- hasAction: exports.has('action'),
700
- hasLoader: exports.has('loader'),
701
- hasClientAction,
702
- hasClientLoader,
703
- hasClientMiddleware,
704
- hasDefaultExport,
705
- hasErrorBoundary: exports.has('ErrorBoundary'),
706
- imports: jsAssets.map((asset)=>combineURLs(assetPrefix, asset)),
707
- css: cssAssets.map((asset)=>combineURLs(assetPrefix, asset))
708
- };
709
- }
710
- let entryAssets = getAssetsForChunk('entry.client'), entryJsAssets = entryAssets.filter((asset)=>asset.endsWith('.js')), entryCssAssets = entryAssets.filter((asset)=>asset.endsWith('.css')), fingerprintedValues = {
711
- entry: {
712
- module: combineURLs(assetPrefix, entryJsAssets[0] || ''),
713
- imports: entryJsAssets.map((asset)=>combineURLs(assetPrefix, asset)),
714
- css: entryCssAssets.map((asset)=>combineURLs(assetPrefix, asset))
715
- },
716
- routes: result
717
- }, version = isBuild ? createHash('md5').update(JSON.stringify(fingerprintedValues)).digest('hex').slice(0, 8) : String(Math.random()), manifestPath = getReactRouterManifestPath({
718
- version,
719
- isBuild,
720
- entryModulePath: entryJsAssets[0]
721
- });
722
- return {
723
- version,
724
- url: combineURLs(assetPrefix, manifestPath),
725
- hmr: void 0,
726
- entry: fingerprintedValues.entry,
727
- sri: void 0,
728
- routes: result
922
+ state = nextState;
923
+ }
924
+ }, runRescan = async ()=>{
925
+ let nextDirectories;
926
+ if (!closed) try {
927
+ if (nextDirectories = await readRouteDirectories(watchDirectory), closed) return;
928
+ let nextState = {
929
+ directories: nextDirectories,
930
+ routeTopology: await getRouteTopology()
931
+ };
932
+ if (closed) return;
933
+ await applyNextState(nextState);
934
+ } catch (error) {
935
+ nextDirectories && !closed && syncDirectoryWatchers(nextDirectories), onError(error);
936
+ }
937
+ }, scheduleRescan = ()=>{
938
+ rescanTimer && clearTimeout(rescanTimer), rescanTimer = setTimeout(()=>{
939
+ rescanTimer = void 0, rescanQueue = rescanQueue.then(runRescan, runRescan);
940
+ }, 100);
729
941
  };
730
- }
731
- let isPlainObject = (value)=>'object' == typeof value && null !== value, validateEntry = (entry, path, issues)=>isPlainObject(entry) && 'then' in entry && 'catch' in entry ? (issues.push(`${path}\nInvalid type: Expected object but received a promise. Did you forget to await?`), !1) : isPlainObject(entry) ? ('string' != typeof entry.file && issues.push(`${path}.file\nInvalid type: Expected string.`), 'id' in entry && 'root' === entry.id && issues.push(`${path}.id\nA route cannot use the reserved id 'root'.`), 'path' in entry && void 0 !== entry.path && 'string' != typeof entry.path && issues.push(`${path}.path\nInvalid type: Expected string.`), 'index' in entry && void 0 !== entry.index && 'boolean' != typeof entry.index && issues.push(`${path}.index\nInvalid type: Expected boolean.`), 'caseSensitive' in entry && void 0 !== entry.caseSensitive && 'boolean' != typeof entry.caseSensitive && issues.push(`${path}.caseSensitive\nInvalid type: Expected boolean.`), 'children' in entry && void 0 !== entry.children && (Array.isArray(entry.children) ? entry.children.forEach((child, index)=>validateEntry(child, `${path}.children.${index}`, issues)) : issues.push(`${path}.children\nInvalid type: Expected array.`)), 0 === issues.length) : (issues.push(`${path}\nInvalid type: Expected object.`), !1), getRouteBranch = (routes, routeId)=>{
942
+ try {
943
+ await applyNextState(discoveredState);
944
+ } catch (error) {
945
+ onError(error);
946
+ }
947
+ return async ()=>{
948
+ if (closed) return void await rescanQueue;
949
+ for (let watcher of (closed = !0, rescanTimer && clearTimeout(rescanTimer), directoryWatchers.values()))watcher.close();
950
+ for (let watcher of (directoryWatchers.clear(), await rescanQueue, directoryWatchers.values()))watcher.close();
951
+ directoryWatchers.clear();
952
+ };
953
+ }, isPlainObject = (value)=>'object' == typeof value && null !== value, validateEntry = (entry, path, issues)=>isPlainObject(entry) && 'then' in entry && 'catch' in entry ? (issues.push(`${path}\nInvalid type: Expected object but received a promise. Did you forget to await?`), !1) : isPlainObject(entry) ? ('string' != typeof entry.file && issues.push(`${path}.file\nInvalid type: Expected string.`), 'id' in entry && 'root' === entry.id && issues.push(`${path}.id\nA route cannot use the reserved id 'root'.`), 'path' in entry && void 0 !== entry.path && 'string' != typeof entry.path && issues.push(`${path}.path\nInvalid type: Expected string.`), 'index' in entry && void 0 !== entry.index && 'boolean' != typeof entry.index && issues.push(`${path}.index\nInvalid type: Expected boolean.`), 'caseSensitive' in entry && void 0 !== entry.caseSensitive && 'boolean' != typeof entry.caseSensitive && issues.push(`${path}.caseSensitive\nInvalid type: Expected boolean.`), 'children' in entry && void 0 !== entry.children && (Array.isArray(entry.children) ? entry.children.forEach((child, index)=>validateEntry(child, `${path}.children.${index}`, issues)) : issues.push(`${path}.children\nInvalid type: Expected array.`)), 0 === issues.length) : (issues.push(`${path}\nInvalid type: Expected object.`), !1), getRouteBranch = (routes, routeId)=>{
732
954
  let branch = [], current = routeId;
733
955
  for(; current;){
734
956
  let route = routes[current];
@@ -742,7 +964,7 @@ let isPlainObject = (value)=>'object' == typeof value && null !== value, validat
742
964
  routes
743
965
  };
744
966
  let rootRelativeRoutes = Object.fromEntries(Object.entries(routes).map(([id, route])=>{
745
- let filePath = resolve(appDirectory, route.file);
967
+ let filePath = external_pathe_resolve(appDirectory, route.file);
746
968
  return [
747
969
  id,
748
970
  {
@@ -750,7 +972,7 @@ let isPlainObject = (value)=>'object' == typeof value && null !== value, validat
750
972
  file: relative(rootDirectory, filePath).replace(/\\/g, '/')
751
973
  }
752
974
  ];
753
- })), serverBuildDirectory = resolve(buildDirectory, 'server'), buildManifest = {
975
+ })), serverBuildDirectory = external_pathe_resolve(buildDirectory, 'server'), buildManifest = {
754
976
  routes: rootRelativeRoutes,
755
977
  serverBundles: {},
756
978
  routeIdToServerBundleId: {}
@@ -773,7 +995,7 @@ let isPlainObject = (value)=>'object' == typeof value && null !== value, validat
773
995
  return {
774
996
  id: (route = {
775
997
  ...branchRoute,
776
- file: resolve(appDirectory, branchRoute.file)
998
+ file: external_pathe_resolve(appDirectory, branchRoute.file)
777
999
  }).id,
778
1000
  path: route.path,
779
1001
  file: route.file,
@@ -787,13 +1009,10 @@ let isPlainObject = (value)=>'object' == typeof value && null !== value, validat
787
1009
  } else if (!/^[a-zA-Z0-9-_]+$/.test(serverBundleId)) throw Error('The "serverBundles" function must only return strings containing alphanumeric characters, hyphens and underscores.');
788
1010
  buildManifest.routeIdToServerBundleId[route.id] = serverBundleId, buildManifest.serverBundles[serverBundleId] ??= {
789
1011
  id: serverBundleId,
790
- file: relative(rootDirectory, resolve(serverBuildDirectory, serverBundleId, serverBuildFile)).replace(/\\/g, '/')
1012
+ file: relative(rootDirectory, external_pathe_resolve(serverBuildDirectory, serverBundleId, serverBuildFile)).replace(/\\/g, '/')
791
1013
  };
792
1014
  })), buildManifest;
793
1015
  };
794
- function getDevtoolFromRspackConfig(config) {
795
- if (config && 'function' != typeof config && 'object' == typeof config) return config.devtool;
796
- }
797
1016
  function pluginId(name) {
798
1017
  return `rsbuild:${name}`;
799
1018
  }
@@ -809,22 +1028,217 @@ let REACT_ROUTER_EXTERNALS = [
809
1028
  '@react-router/express',
810
1029
  '@react-router/node',
811
1030
  '@react-router/serve'
812
- ], requireFromHere = createRequire(import.meta.url);
1031
+ ], requireFromHere = createRequire(import.meta.url), roundMs = (value)=>Math.round(10 * value) / 10, VIRTUAL_MODULE_PREFIX = 'virtual/react-router/', isLatestStartedCompilation = (identity, start)=>!identity || start?.status === 'started' && start.identity === identity, hasPendingCompilation = (pair)=>pair.latestWebStart?.status === 'pending' || pair.latestNodeStart?.status === 'pending', snapshotDevChangedFiles = (compiler)=>compiler ? {
1032
+ known: void 0 !== compiler.modifiedFiles || void 0 !== compiler.removedFiles,
1033
+ files: new Set([
1034
+ ...compiler.modifiedFiles ?? [],
1035
+ ...compiler.removedFiles ?? []
1036
+ ])
1037
+ } : {
1038
+ known: !1,
1039
+ files: new Set()
1040
+ }, snapshotDependencies = (compilation)=>({
1041
+ files: new Set([
1042
+ ...compilation.fileDependencies,
1043
+ ...compilation.buildDependencies ?? []
1044
+ ]),
1045
+ contexts: new Set(compilation.contextDependencies),
1046
+ missing: new Set(compilation.missingDependencies)
1047
+ }), isWithinDirectory = (directory, file)=>{
1048
+ let relativePath = external_node_path_relative(directory, file);
1049
+ return '' === relativePath || !relativePath.startsWith('..') && !external_node_path_isAbsolute(relativePath);
1050
+ }, getEnvironmentStats = (stats, name)=>(Array.isArray(stats.stats) ? stats.stats : [
1051
+ stats
1052
+ ]).find((child)=>{
1053
+ let compilation = child.compilation;
1054
+ return compilation.name === name || compilation.compiler?.name === name;
1055
+ }), evaluateServerBuild = async (server, entryName)=>resolveServerBuildModule(await server.environments.node.loadBundle(entryName), `Server entry ${JSON.stringify(entryName)}`), evaluateServerBuilds = async (server, entryNames)=>Object.fromEntries(await Promise.all(entryNames.map(async (entryName)=>[
1056
+ entryName,
1057
+ await evaluateServerBuild(server, entryName)
1058
+ ]))), pinBuildToManifest = (entryName, build, manifest)=>{
1059
+ for (let [routeId, manifestRoute] of Object.entries(manifest.routes)){
1060
+ let routeModule = build.routes[routeId]?.module;
1061
+ if (!routeModule) throw Error(`[rsbuild-plugin-react-router] Server build ${JSON.stringify(entryName)} route ${JSON.stringify(routeId)} is missing from the evaluated server build.`);
1062
+ if (!!manifestRoute.hasLoader != ('function' == typeof routeModule.loader)) throw Error(`[rsbuild-plugin-react-router] Server build ${JSON.stringify(entryName)} route ${JSON.stringify(routeId)} loader export does not match its web manifest.`);
1063
+ if (!!manifestRoute.hasAction != ('function' == typeof routeModule.action)) throw Error(`[rsbuild-plugin-react-router] Server build ${JSON.stringify(entryName)} route ${JSON.stringify(routeId)} action export does not match its web manifest.`);
1064
+ }
1065
+ return {
1066
+ ...build,
1067
+ assets: structuredClone(manifest)
1068
+ };
1069
+ }, collectManifestCssAssetOwnership = (manifest)=>{
1070
+ let ownership = new Set();
1071
+ for (let asset of manifest.entry?.css ?? [])ownership.add(`entry\0${asset}`);
1072
+ for (let [routeId, route] of Object.entries(manifest.routes ?? {}))for (let asset of route.css ?? [])ownership.add(`route\0${routeId}\0${asset}`);
1073
+ return ownership;
1074
+ }, hasRemovedCssAssetOwnership = (previous, next)=>{
1075
+ for (let [entryName, previousManifest] of Object.entries(previous)){
1076
+ let previousOwnership = collectManifestCssAssetOwnership(previousManifest);
1077
+ if (0 === previousOwnership.size) continue;
1078
+ let nextManifest = next[entryName];
1079
+ if (!nextManifest) return !0;
1080
+ let nextOwnership = collectManifestCssAssetOwnership(nextManifest);
1081
+ for (let owner of previousOwnership)if (!nextOwnership.has(owner)) return !0;
1082
+ }
1083
+ return !1;
1084
+ }, normalizeManifestForCssOwnershipCheck = (manifest)=>{
1085
+ let cssAssets = ((manifest)=>{
1086
+ let assets = new Set(manifest.entry?.css ?? []);
1087
+ for (let route of Object.values(manifest.routes ?? {}))for (let asset of route.css ?? [])assets.add(asset);
1088
+ return assets;
1089
+ })(manifest), nonCssImports = (imports = [])=>imports.filter((importPath)=>!cssAssets.has(importPath));
1090
+ return {
1091
+ entry: {
1092
+ imports: nonCssImports(manifest.entry?.imports),
1093
+ module: manifest.entry?.module
1094
+ },
1095
+ routes: Object.fromEntries(Object.entries(manifest.routes ?? {}).sort(([left], [right])=>left.localeCompare(right)).map(([routeId, route])=>[
1096
+ routeId,
1097
+ {
1098
+ caseSensitive: route.caseSensitive,
1099
+ clientActionModule: route.clientActionModule,
1100
+ clientLoaderModule: route.clientLoaderModule,
1101
+ clientMiddlewareModule: route.clientMiddlewareModule,
1102
+ errorBoundary: route.hasErrorBoundary,
1103
+ hasAction: route.hasAction,
1104
+ hasClientAction: route.hasClientAction,
1105
+ hasClientLoader: route.hasClientLoader,
1106
+ hasClientMiddleware: route.hasClientMiddleware,
1107
+ hasDefaultExport: route.hasDefaultExport,
1108
+ hasLoader: route.hasLoader,
1109
+ hydrateFallbackModule: route.hydrateFallbackModule,
1110
+ id: route.id,
1111
+ imports: nonCssImports(route.imports),
1112
+ index: route.index,
1113
+ module: route.module,
1114
+ parentId: route.parentId,
1115
+ path: route.path
1116
+ }
1117
+ ]))
1118
+ };
1119
+ }, hasSameRouteMetadata = (previous, next)=>previous.caseSensitive === next.caseSensitive && previous.clientActionModule === next.clientActionModule && previous.clientLoaderModule === next.clientLoaderModule && previous.clientMiddlewareModule === next.clientMiddlewareModule && previous.hasErrorBoundary === next.hasErrorBoundary && previous.hasAction === next.hasAction && previous.hasClientAction === next.hasClientAction && previous.hasClientLoader === next.hasClientLoader && previous.hasClientMiddleware === next.hasClientMiddleware && previous.hasDefaultExport === next.hasDefaultExport && previous.hasLoader === next.hasLoader && previous.hydrateFallbackModule === next.hydrateFallbackModule && previous.id === next.id && previous.index === next.index && previous.parentId === next.parentId && previous.path === next.path, createDeferred = ()=>{
1120
+ let resolve, reject, promise = new Promise((resolvePromise, rejectPromise)=>{
1121
+ resolve = resolvePromise, reject = rejectPromise;
1122
+ });
1123
+ return promise.catch(()=>void 0), {
1124
+ promise,
1125
+ resolve,
1126
+ reject
1127
+ };
1128
+ }, DEV_RUNTIME_KEY = Symbol.for('rsbuild-plugin-react-router.dev-runtime.v1'), loadReactRouterServerBuild = (server, entryName)=>{
1129
+ let runtime = Reflect.get(server, DEV_RUNTIME_KEY);
1130
+ return runtime ? runtime.load(entryName) : Promise.reject(Error('[rsbuild-plugin-react-router] This Rsbuild development server is not registered with the React Router plugin. Add pluginReactRouter() before calling loadReactRouterServerBuild().'));
1131
+ }, config_imports_normalizePath = (filePath)=>external_pathe_resolve(filePath), isNodeModulePath = (filePath)=>filePath.split(/[\\/]/).includes('node_modules'), collectConfigImportWatchPaths = (configPath, moduleCache, previousCacheKeys)=>{
1132
+ let normalizedConfigPath = config_imports_normalizePath(configPath), watchPaths = new Set();
1133
+ for (let [cacheKey, module] of Object.entries(moduleCache)){
1134
+ if (previousCacheKeys.has(cacheKey)) continue;
1135
+ let importPath = config_imports_normalizePath(module?.filename ?? cacheKey);
1136
+ importPath === normalizedConfigPath || isNodeModulePath(importPath) || watchPaths.add(importPath);
1137
+ }
1138
+ return Array.from(watchPaths);
1139
+ };
813
1140
  var src_dirname = __rspack_dirname(__rspack_fileURLToPath(import.meta.url));
814
- let redirectStatusCodes = new Set([
815
- 301,
816
- 302,
817
- 303,
818
- 307,
819
- 308
820
- ]), pluginReactRouter = (options = {})=>({
1141
+ let cssUrlAssetExtensions = /\.(?:css|less|sass|scss|styl|stylus|pcss|postcss|sss)$/, urlAssetResourceQuery = /^(?=.*(?:\?|&)url(?:&|$))(?!.*(?:\?|&)(?:raw|inline)(?:&|$))/, pluginReactRouter = (options = {})=>({
821
1142
  name: PLUGIN_NAME,
822
1143
  async setup (api) {
823
- let routeDiscovery, clientStats, pluginOptions = {
1144
+ let routeDiscovery, closeRouteTopologyWatcher, clientStats, typegenProcess, pluginOptions = {
824
1145
  customServer: !1,
825
1146
  serverOutput: 'module',
826
1147
  ...options
827
- }, nodeExternals = Array.from(new Set([
1148
+ }, logPerformance = !0 === pluginOptions.logPerformance, setupStartMs = logPerformance ? performance.now() : 0, performanceProfiler = (({ enabled, log })=>{
1149
+ let timingsByEnvironment = new Map(), recordDuration = (environment, operation, resource, startMs, endMs)=>{
1150
+ let timings, timing, duration = endMs - startMs, timing1 = ((timings = timingsByEnvironment.get(environment)) || (timings = new Map(), timingsByEnvironment.set(environment, timings)), (timing = timings.get(operation)) || (timing = {
1151
+ count: 0,
1152
+ totalMs: 0,
1153
+ maxMs: 0,
1154
+ slowest: [],
1155
+ intervals: []
1156
+ }, timings.set(operation, timing)), timing);
1157
+ timing1.count += 1, timing1.totalMs += duration, timing1.maxMs = Math.max(timing1.maxMs, duration), timing1.intervals.push({
1158
+ startMs,
1159
+ endMs
1160
+ }), ((slowest, entry)=>{
1161
+ if (5 === slowest.length && entry.durationMs <= slowest[slowest.length - 1].durationMs) return;
1162
+ let insertIndex = slowest.length;
1163
+ for(; insertIndex > 0 && entry.durationMs > slowest[insertIndex - 1].durationMs;)insertIndex -= 1;
1164
+ slowest.splice(insertIndex, 0, entry), slowest.length > 5 && slowest.pop();
1165
+ })(timing1.slowest, {
1166
+ durationMs: duration,
1167
+ resource
1168
+ });
1169
+ };
1170
+ return {
1171
+ record (environment, operation, resource, callback) {
1172
+ if (!enabled) try {
1173
+ return Promise.resolve(callback());
1174
+ } catch (error) {
1175
+ return Promise.reject(error);
1176
+ }
1177
+ let resolvedEnvironment = environment ?? 'unknown', start = performance.now();
1178
+ try {
1179
+ return callback().then((result)=>{
1180
+ let end = performance.now();
1181
+ return recordDuration(resolvedEnvironment, operation, resource, start, end), result;
1182
+ }, (error)=>{
1183
+ let end = performance.now();
1184
+ throw recordDuration(resolvedEnvironment, operation, resource, start, end), error;
1185
+ });
1186
+ } catch (error) {
1187
+ return recordDuration(resolvedEnvironment, operation, resource, start, performance.now()), Promise.reject(error);
1188
+ }
1189
+ },
1190
+ recordSync (environment, operation, resource, callback) {
1191
+ if (!enabled) return callback();
1192
+ let start = performance.now();
1193
+ try {
1194
+ return callback();
1195
+ } finally{
1196
+ recordDuration(environment ?? 'unknown', operation, resource, start, performance.now());
1197
+ }
1198
+ },
1199
+ flush (environment, details = {}) {
1200
+ if (!enabled) return;
1201
+ let resolvedEnvironment = environment ?? 'unknown', timings = timingsByEnvironment.get(resolvedEnvironment);
1202
+ if (!timings || 0 === timings.size) return;
1203
+ let operations = Object.fromEntries([
1204
+ ...timings.entries()
1205
+ ].map(([operation, timing])=>[
1206
+ operation,
1207
+ {
1208
+ count: timing.count,
1209
+ totalMs: roundMs(timing.totalMs),
1210
+ wallMs: ((intervals)=>{
1211
+ if (0 === intervals.length) return 0;
1212
+ let sortedIntervals = [
1213
+ ...intervals
1214
+ ].sort((a, b)=>a.startMs - b.startMs || a.endMs - b.endMs), mergedStart = sortedIntervals[0].startMs, mergedEnd = sortedIntervals[0].endMs, wallMs = 0;
1215
+ for (let interval of sortedIntervals.slice(1)){
1216
+ if (interval.startMs <= mergedEnd) {
1217
+ mergedEnd = Math.max(mergedEnd, interval.endMs);
1218
+ continue;
1219
+ }
1220
+ wallMs += mergedEnd - mergedStart, mergedStart = interval.startMs, mergedEnd = interval.endMs;
1221
+ }
1222
+ return roundMs(wallMs += mergedEnd - mergedStart);
1223
+ })(timing.intervals),
1224
+ maxMs: roundMs(timing.maxMs),
1225
+ slowest: timing.slowest.map((entry)=>({
1226
+ durationMs: roundMs(entry.durationMs),
1227
+ resource: entry.resource
1228
+ }))
1229
+ }
1230
+ ])), report = {
1231
+ environment: resolvedEnvironment,
1232
+ ...details,
1233
+ operations
1234
+ };
1235
+ log(`[react-router:performance] ${JSON.stringify(report)}`), timingsByEnvironment.delete(resolvedEnvironment);
1236
+ }
1237
+ };
1238
+ })({
1239
+ enabled: logPerformance,
1240
+ log: (message)=>api.logger.info(message)
1241
+ }), nodeExternals = Array.from(new Set([
828
1242
  'express',
829
1243
  ...function(rootDirectory) {
830
1244
  let externals = [];
@@ -891,11 +1305,11 @@ let redirectStatusCodes = new Set([
891
1305
  let envTools = normalized.environments?.[clientEnvName]?.tools?.rspack, rootTools = normalized.tools?.rspack;
892
1306
  return getDevtoolFromRspackConfig(envTools) ?? getDevtoolFromRspackConfig(rootTools);
893
1307
  }(normalized, clientEnvName);
894
- (!0 === sourceMapSetting || !1 !== sourceMapSetting && null != sourceMapSetting && ('string' == typeof sourceMapSetting || 'object' == typeof sourceMapSetting && sourceMapSetting.js) || !0 === devtoolSetting || null != devtoolSetting && !1 !== devtoolSetting && ('string' == typeof devtoolSetting ? devtoolSetting.includes('source-map') : 'object' == typeof devtoolSetting)) && warn("\n WARNING: Source maps are enabled in production\n This makes your server code publicly visible in the browser.\n This is highly discouraged! If you insist, ensure that you are using\n environment variables for secrets and not hard-coding them in your source code.\n");
1308
+ (isSourceMapEnabled(sourceMapSetting) || !0 === devtoolSetting || null != devtoolSetting && !1 !== devtoolSetting && ('string' == typeof devtoolSetting ? devtoolSetting.includes('source-map') : 'object' == typeof devtoolSetting)) && warn("\n WARNING: Source maps are enabled in production\n This makes your server code publicly visible in the browser.\n This is highly discouraged! If you insist, ensure that you are using\n environment variables for secrets and not hard-coding them in your source code.\n");
895
1309
  }(api.getNormalizedConfig(), (msg)=>api.logger.warn(msg), 'web');
896
1310
  }), api.onBeforeStartDevServer(async ()=>{
897
- let { execa } = await import("execa");
898
- execa('npx', [
1311
+ if (typegenProcess) return;
1312
+ let { execa } = await import("execa"), process1 = execa('npx', [
899
1313
  '--yes',
900
1314
  'react-router',
901
1315
  'typegen',
@@ -904,7 +1318,13 @@ let redirectStatusCodes = new Set([
904
1318
  stdio: 'inherit',
905
1319
  detached: !1,
906
1320
  cleanup: !0
907
- }).catch(()=>{});
1321
+ });
1322
+ typegenProcess = process1, process1.catch(()=>{}).finally(()=>{
1323
+ typegenProcess === process1 && (typegenProcess = void 0);
1324
+ });
1325
+ }), api.onCloseDevServer(async ()=>{
1326
+ let process1 = typegenProcess;
1327
+ typegenProcess = void 0, process1 && (process1.kill('SIGTERM'), await process1.catch(()=>void 0));
908
1328
  }), api.onBeforeBuild(async ()=>{
909
1329
  let { execa } = await import("execa");
910
1330
  await execa('npx', [
@@ -915,29 +1335,48 @@ let redirectStatusCodes = new Set([
915
1335
  stdio: 'inherit'
916
1336
  });
917
1337
  });
918
- let jiti = createJiti(process.cwd()), configPath = findEntryFile(resolve('react-router.config')), configExists = existsSync(configPath), reactRouterUserConfig = {};
1338
+ let configPath = findEntryFile(external_pathe_resolve('react-router.config')), configExists = existsSync(configPath), configWatchPaths = configExists ? configPath : JS_EXTENSIONS.map((extension)=>external_pathe_resolve(`react-router.config${extension}`)), reactRouterUserConfig = {};
919
1339
  if (configExists) {
920
- let displayPath = relative(process.cwd(), configPath);
1340
+ let displayPath = relative(process.cwd(), configPath), configJiti = createJiti(process.cwd(), {
1341
+ moduleCache: !0
1342
+ }), cacheKeysBeforeImport = new Set(Object.keys(configJiti.cache));
921
1343
  try {
922
- let imported = await jiti.import(configPath, {
1344
+ let imported = await configJiti.import(configPath, {
923
1345
  default: !0
924
- });
925
- if (void 0 === imported) throw Error(`${displayPath} must provide a default export`);
1346
+ }), importedConfigPaths = collectConfigImportWatchPaths(configPath, configJiti.cache, cacheKeysBeforeImport);
1347
+ if (importedConfigPaths.length > 0 && (configWatchPaths = [
1348
+ configPath,
1349
+ ...importedConfigPaths
1350
+ ]), void 0 === imported) throw Error(`${displayPath} must provide a default export`);
926
1351
  if ('object' != typeof imported) throw Error(`${displayPath} must export a config`);
927
1352
  reactRouterUserConfig = imported;
928
1353
  } catch (error) {
929
1354
  throw Error(`Error loading ${displayPath}: ${error}`);
1355
+ } finally{
1356
+ ((moduleCache, filePaths)=>{
1357
+ let normalizedFilePaths = new Set(filePaths.map(config_imports_normalizePath));
1358
+ for (let [cacheKey, module] of Object.entries(moduleCache)){
1359
+ let cachedPath = config_imports_normalizePath(module?.filename ?? cacheKey);
1360
+ normalizedFilePaths.has(cachedPath) && delete moduleCache[cacheKey];
1361
+ }
1362
+ })(configJiti.cache, [
1363
+ configPath,
1364
+ ...collectConfigImportWatchPaths(configPath, configJiti.cache, cacheKeysBeforeImport)
1365
+ ]);
930
1366
  }
931
1367
  } else console.warn('No react-router.config found, using default configuration.');
932
- let { resolved: resolvedConfig, presets: configPresets } = await resolveReactRouterConfig(reactRouterUserConfig), { appDirectory, basename, buildDirectory, future, allowedActionOrigins, routeDiscovery: userRouteDiscovery, ssr, prerender: prerenderConfig, serverBuildFile, serverModuleFormat, serverBundles, buildEnd } = resolvedConfig, hasExplicitServerOutput = Object.prototype.hasOwnProperty.call(options, 'serverOutput'), resolvedServerOutput = hasExplicitServerOutput ? options.serverOutput : 'cjs' === serverModuleFormat ? 'commonjs' : 'module';
933
- if (hasExplicitServerOutput && serverModuleFormat && ('commonjs' === options.serverOutput ? 'cjs' : 'esm') !== serverModuleFormat && api.logger.warn(`[${PLUGIN_NAME}] Both \`serverOutput\` and \`serverModuleFormat\` are set. Using \`serverOutput=${options.serverOutput}\` and ignoring \`serverModuleFormat=${serverModuleFormat}\`.`), serverBuildFile && !serverBuildFile.endsWith('.js')) throw Error('The `serverBuildFile` config must end in `.js`.');
1368
+ let jiti = createJiti(process.cwd(), {
1369
+ moduleCache: !1
1370
+ }), { resolved: resolvedConfig, presets: configPresets, hasConfiguredServerModuleFormat } = await resolveReactRouterConfig(reactRouterUserConfig), { appDirectory, basename, buildDirectory, future, allowedActionOrigins, routeDiscovery: userRouteDiscovery, ssr, prerender: prerenderConfig, serverBuildFile, serverModuleFormat, splitRouteModules, buildEnd } = resolvedConfig, hasExplicitServerOutput = Object.prototype.hasOwnProperty.call(options, 'serverOutput'), resolvedServerOutput = pluginOptions.serverOutput;
1371
+ if (hasExplicitServerOutput || (resolvedServerOutput = 'cjs' === serverModuleFormat ? 'commonjs' : 'module'), hasExplicitServerOutput && hasConfiguredServerModuleFormat && serverModuleFormat && ('commonjs' === resolvedServerOutput ? 'cjs' : 'esm') !== serverModuleFormat && api.logger.warn(`[${PLUGIN_NAME}] Both \`serverOutput\` and \`serverModuleFormat\` are set. Using \`serverOutput=${resolvedServerOutput}\` and ignoring \`serverModuleFormat=${serverModuleFormat}\`.`), serverBuildFile && !serverBuildFile.endsWith('.js')) throw Error('The `serverBuildFile` config must end in `.js`.');
934
1372
  if ('esm' !== serverModuleFormat && 'cjs' !== serverModuleFormat) throw Error('The `serverModuleFormat` config must be "esm" or "cjs".');
935
- serverBundles && api.logger.warn(`[${PLUGIN_NAME}] \`serverBundles\` is configured. Rsbuild currently emits a single server bundle, but the build manifest will include the server bundle mapping for compatibility.`);
936
1373
  let prerenderConfigError = ((prerender)=>{
1374
+ let value;
937
1375
  if (!prerender) return null;
938
- if (!(isValidPrerenderPathsConfig('object' == typeof prerender && null !== prerender && 'paths' in prerender ? prerender?.paths : prerender) || 'object' == typeof prerender && null !== prerender && 'paths' in prerender && isValidPrerenderPathsConfig(prerender?.paths))) return 'The `prerender`/`prerender.paths` config must be a boolean, an array of string paths, or a function returning a boolean or array of string paths.';
939
- let concurrency = 'object' == typeof prerender && null !== prerender && 'unstable_concurrency' in prerender ? prerender?.unstable_concurrency : void 0;
940
- return void 0 !== concurrency && (!Number.isInteger(concurrency) || concurrency <= 0) ? 'The `prerender.unstable_concurrency` config must be a positive integer if specified.' : null;
1376
+ let config = getPrerenderConfigObject(prerender);
1377
+ if (!('boolean' == typeof (value = config && 'paths' in config ? config.paths : prerender) || 'function' == typeof value || Array.isArray(value))) return 'The `prerender`/`prerender.paths` config must be a boolean, an array of string paths, or a function returning a boolean or array of string paths.';
1378
+ let concurrency = getPrerenderConcurrencyConfig(config);
1379
+ return concurrency && (!Number.isInteger(concurrency.value) || concurrency.value <= 0) ? `The \`${concurrency.key}\` config must be a positive integer if specified.` : null;
941
1380
  })(prerenderConfig);
942
1381
  if (prerenderConfigError) throw Error(prerenderConfigError);
943
1382
  if (userRouteDiscovery) {
@@ -954,62 +1393,76 @@ let redirectStatusCodes = new Set([
954
1393
  } : {
955
1394
  mode: 'initial'
956
1395
  };
957
- globalThis.__reactRouterAppDirectory = resolve(appDirectory);
958
- let routesPath = findEntryFile(resolve(appDirectory, 'routes'));
1396
+ globalThis.__reactRouterAppDirectory = external_pathe_resolve(appDirectory);
1397
+ let routesPath = findEntryFile(external_pathe_resolve(appDirectory, 'routes'));
959
1398
  if (!existsSync(routesPath)) throw Error(`Route config file not found at "${relative(process.cwd(), routesPath)}".`);
960
- let routeConfigExport = await jiti.import(routesPath, {
961
- default: !0
962
- }), routeConfigValue = await routeConfigExport, validation = (({ routeConfigFile, routeConfig })=>{
963
- if (!routeConfig) return {
964
- valid: !1,
965
- message: `Route config must be the default export in "${routeConfigFile}".`
966
- };
967
- if (!Array.isArray(routeConfig)) return {
968
- valid: !1,
969
- message: `Route config in "${routeConfigFile}" must be an array.`
970
- };
971
- let issues = [];
972
- return (routeConfig.forEach((entry, index)=>validateEntry(entry, `routes.${index}`, issues)), issues.length > 0) ? {
973
- valid: !1,
974
- message: [
975
- `Route config in "${routeConfigFile}" is invalid.`,
976
- issues.join('\n\n')
977
- ].join('\n\n')
978
- } : {
979
- valid: !0,
980
- routeConfig: routeConfig
981
- };
982
- })({
983
- routeConfigFile: relative(process.cwd(), routesPath),
984
- routeConfig: routeConfigValue
985
- });
986
- if (!validation.valid) throw Error(validation.message);
987
- let routeConfig = validation.routeConfig, entryClientPath = findEntryFile(resolve(appDirectory, 'entry.client')), entryServerPath = findEntryFile(resolve(appDirectory, 'entry.server')), serverAppPath = findEntryFile(resolve(appDirectory, '../server/index')), hasServerApp = existsSync(serverAppPath), templateDir = resolve(src_dirname, 'templates'), templateClientPath = resolve(templateDir, 'entry.client.js'), templateServerPath = resolve(templateDir, 'entry.server.js'), finalEntryClientPath = existsSync(entryClientPath) ? entryClientPath : templateClientPath, finalEntryServerPath = existsSync(entryServerPath) ? entryServerPath : templateServerPath, rootRoutePath = findEntryFile(resolve(appDirectory, 'root')), rootRouteFile = relative(appDirectory, rootRoutePath), routes = {
1399
+ let loadRouteConfig = async ()=>{
1400
+ let routeConfigExport = await jiti.import(routesPath, {
1401
+ default: !0
1402
+ }), routeConfigValue = await routeConfigExport, validation = (({ routeConfigFile, routeConfig })=>{
1403
+ if (!routeConfig) return {
1404
+ valid: !1,
1405
+ message: `Route config must be the default export in "${routeConfigFile}".`
1406
+ };
1407
+ if (!Array.isArray(routeConfig)) return {
1408
+ valid: !1,
1409
+ message: `Route config in "${routeConfigFile}" must be an array.`
1410
+ };
1411
+ let issues = [];
1412
+ return (routeConfig.forEach((entry, index)=>validateEntry(entry, `routes.${index}`, issues)), issues.length > 0) ? {
1413
+ valid: !1,
1414
+ message: [
1415
+ `Route config in "${routeConfigFile}" is invalid.`,
1416
+ issues.join('\n\n')
1417
+ ].join('\n\n')
1418
+ } : {
1419
+ valid: !0,
1420
+ routeConfig: routeConfig
1421
+ };
1422
+ })({
1423
+ routeConfigFile: relative(process.cwd(), routesPath),
1424
+ routeConfig: routeConfigValue
1425
+ });
1426
+ if (!validation.valid) throw Error(validation.message);
1427
+ return validation.routeConfig;
1428
+ }, routeConfig = await loadRouteConfig(), entryClientPath = findEntryFile(external_pathe_resolve(appDirectory, 'entry.client')), entryServerPath = findEntryFile(external_pathe_resolve(appDirectory, 'entry.server')), serverAppPath = findEntryFile(external_pathe_resolve(appDirectory, '../server/index')), hasServerApp = existsSync(serverAppPath), devServerBuildEntryName = hasServerApp ? 'static/js/react-router-server-build' : 'static/js/app', templateDir = external_pathe_resolve(src_dirname, 'templates'), templateClientPath = external_pathe_resolve(templateDir, 'entry.client.js'), templateServerPath = external_pathe_resolve(templateDir, 'entry.server.js'), finalEntryClientPath = existsSync(entryClientPath) ? entryClientPath : templateClientPath, finalEntryServerPath = existsSync(entryServerPath) ? entryServerPath : templateServerPath, rootRoutePath = findEntryFile(external_pathe_resolve(appDirectory, 'root')), rootRouteFile = relative(appDirectory, rootRoutePath), createRouteTopologySnapshot = (routeFile, routeConfig)=>{
1429
+ let routes;
1430
+ return new Set((Array.isArray(routes = [
1431
+ [
1432
+ 'root',
1433
+ {
1434
+ path: '',
1435
+ id: 'root',
1436
+ file: routeFile
1437
+ }
1438
+ ],
1439
+ ...configRoutesToRouteManifestEntries(appDirectory, routeConfig)
1440
+ ]) ? routes : Object.entries(routes)).map(([routeId, route], order)=>JSON.stringify([
1441
+ order,
1442
+ routeId,
1443
+ route.id,
1444
+ route.parentId ?? null,
1445
+ route.path ?? null,
1446
+ route.index ?? null,
1447
+ route.caseSensitive ?? null,
1448
+ route.file
1449
+ ])));
1450
+ }, getWatchedRouteTopology = async ()=>{
1451
+ let latestRouteConfig = await loadRouteConfig();
1452
+ return createRouteTopologySnapshot(relative(appDirectory, findEntryFile(external_pathe_resolve(appDirectory, 'root'))), latestRouteConfig);
1453
+ }, routes = {
988
1454
  root: {
989
1455
  path: '',
990
1456
  id: 'root',
991
1457
  file: rootRouteFile
992
1458
  },
993
1459
  ...function(appDirectory, routes, rootId = 'root') {
994
- let routeManifest = {};
995
- for (let route of routes)!function walk(route, parentId) {
996
- let id = route.id || normalize(route.file.replace(/\.[^/.]+$/, '')), manifestItem = {
997
- id,
998
- parentId,
999
- file: isAbsolute(route.file) ? relative(appDirectory, route.file) : route.file,
1000
- path: route.path,
1001
- index: route.index,
1002
- caseSensitive: route.caseSensitive
1003
- };
1004
- if (Object.prototype.hasOwnProperty.call(routeManifest, id)) throw Error(`Unable to define routes with duplicate route id: "${id}"`);
1005
- if (routeManifest[id] = manifestItem, route.children) for (let child of route.children)walk(child, id);
1006
- }(route, rootId);
1007
- return routeManifest;
1460
+ return Object.fromEntries(configRoutesToRouteManifestEntries(appDirectory, routes, rootId));
1008
1461
  }(appDirectory, routeConfig)
1009
1462
  }, resolvedConfigWithRoutes = {
1010
1463
  ...resolvedConfig,
1011
- appDirectory: resolve(appDirectory),
1012
- buildDirectory: resolve(buildDirectory),
1464
+ appDirectory: external_pathe_resolve(appDirectory),
1465
+ buildDirectory: external_pathe_resolve(buildDirectory),
1013
1466
  routeDiscovery,
1014
1467
  prerender: prerenderConfig,
1015
1468
  routes,
@@ -1019,224 +1472,616 @@ let redirectStatusCodes = new Set([
1019
1472
  for (let preset of configPresets)await preset.reactRouterConfigResolved?.({
1020
1473
  reactRouterConfig: resolvedConfigForPreset
1021
1474
  });
1022
- let isBuild = 'build' === api.context.action, splitRouteModules = future?.v8_splitRouteModules ?? !1, enforceSplitRouteModules = 'enforce' === splitRouteModules, routeChunkConfig = {
1023
- splitRouteModules,
1024
- appDirectory,
1025
- rootRouteFile
1026
- }, routeChunkCache = new Map(), routeChunkOptions = {
1475
+ let isBuild = 'build' === api.context.action, isPrerenderEnabled = void 0 !== prerenderConfig && !1 !== prerenderConfig, isSpaMode = !ssr && !isPrerenderEnabled, routeCount = Object.keys(routes).length, routeChunkCache = new Map(), routeTransformExecutor = (({ parallelRouteTransform, routeChunkCache, splitRouteModules } = {})=>{
1476
+ let options = {
1477
+ routeChunkCache
1478
+ };
1479
+ if (void 0 === parallelRouteTransform || !1 === parallelRouteTransform) return {
1480
+ run: (task)=>executeRouteTransformTask(task, options),
1481
+ close: async ()=>{}
1482
+ };
1483
+ let workerCount = ((parallelRouteTransform)=>{
1484
+ if (!0 === parallelRouteTransform) return getDefaultConcurrency(void 0);
1485
+ if (!Number.isInteger(parallelRouteTransform) || parallelRouteTransform < 1) throw Error('[react-router] parallelRouteTransform must be true, false, or a positive integer.');
1486
+ return parallelRouteTransform;
1487
+ })(parallelRouteTransform);
1488
+ return workerCount < 1 ? {
1489
+ run: (task)=>executeRouteTransformTask(task, options),
1490
+ close: async ()=>{}
1491
+ } : new ParallelRouteTransformExecutor(workerCount, options, !!splitRouteModules);
1492
+ })({
1493
+ parallelRouteTransform: pluginOptions.parallelRouteTransform ?? routeCount >= 256,
1494
+ routeChunkCache,
1495
+ splitRouteModules: !!splitRouteModules
1496
+ }), routeChunkOptions = {
1027
1497
  splitRouteModules,
1028
1498
  rootRouteFile,
1029
1499
  isBuild,
1030
1500
  cache: routeChunkCache
1031
- }, latestServerManifest = null, latestServerManifestsByBundleId = {}, routeByFilePath = new Map(Object.values(routes).map((route)=>[
1032
- resolve(appDirectory, route.file),
1501
+ }, outputClientPath = external_pathe_resolve(buildDirectory, 'client'), assetsBuildDirectory = relative(process.cwd(), outputClientPath), watchDirectory = external_pathe_resolve(appDirectory), routeRestartMarkerPath = external_pathe_resolve(outputClientPath, '.react-router/route-watch'), routeWatchFiles = [
1502
+ {
1503
+ paths: configWatchPaths,
1504
+ type: 'reload-server'
1505
+ },
1506
+ ...pluginOptions.onRouteTopologyChange ? [] : [
1507
+ {
1508
+ paths: routesPath,
1509
+ type: 'reload-server'
1510
+ },
1511
+ {
1512
+ paths: routeRestartMarkerPath,
1513
+ type: 'reload-server'
1514
+ }
1515
+ ]
1516
+ ];
1517
+ api.onBeforeStartDevServer(async ()=>{
1518
+ await ensureDevRestartMarker(routeRestartMarkerPath), closeRouteTopologyWatcher = await createRouteTopologyWatcher({
1519
+ watchDirectory,
1520
+ getRouteTopology: getWatchedRouteTopology,
1521
+ initialRouteTopology: createRouteTopologySnapshot(rootRouteFile, routeConfig),
1522
+ restartMarkerPath: routeRestartMarkerPath,
1523
+ onRouteTopologyChange: pluginOptions.onRouteTopologyChange,
1524
+ onError: (error)=>{
1525
+ api.logger.warn(`[${PLUGIN_NAME}] Failed to watch route topology changes: ${error}`);
1526
+ }
1527
+ });
1528
+ }), api.onCloseDevServer(async ()=>{
1529
+ await closeRouteTopologyWatcher?.(), closeRouteTopologyWatcher = void 0;
1530
+ }), api.onCloseBuild(async ()=>{
1531
+ await routeTransformExecutor.close();
1532
+ }), api.onCloseDevServer(async ()=>{
1533
+ await routeTransformExecutor.close();
1534
+ });
1535
+ let latestBrowserManifest = null, latestBrowserManifestModuleExports = {}, latestServerManifest = null, latestServerManifestsByBundleId = {}, routeByFilePath = new Map(Object.values(routes).map((route)=>[
1536
+ external_pathe_resolve(appDirectory, route.file),
1033
1537
  route
1034
- ])), routeExportsCache = new Map(), getCachedRouteExports = async (filePath)=>{
1035
- if (routeExportsCache.has(filePath)) return routeExportsCache.get(filePath);
1036
- let exports = await getRouteModuleExports(filePath);
1037
- return routeExportsCache.set(filePath, exports), exports;
1038
- }, webRouteEntries = Object.values(routes).reduce((acc, route)=>{
1039
- let entryName = route.file.slice(0, route.file.lastIndexOf('.')), routeFilePath = resolve(appDirectory, route.file);
1040
- if (acc[entryName] = {
1041
- import: `${routeFilePath}${BUILD_CLIENT_ROUTE_QUERY_STRING}`
1538
+ ])), manifestChunkNames = new Set([
1539
+ 'entry.client'
1540
+ ]), webRouteEntries = Object.values(routes).reduce((acc, route)=>{
1541
+ let entryName = route.file.slice(0, route.file.lastIndexOf('.')), routeFilePath = external_pathe_resolve(appDirectory, route.file);
1542
+ if (manifestChunkNames.add(entryName), acc[entryName] = {
1543
+ import: `${routeFilePath}${BUILD_CLIENT_ROUTE_QUERY_STRING}`,
1544
+ html: !1
1042
1545
  }, isBuild && splitRouteModules && 'root' !== route.id) {
1043
- let source = '';
1546
+ let source;
1044
1547
  try {
1045
1548
  source = readFileSync(routeFilePath, 'utf8');
1046
- } catch {
1047
- source = '';
1549
+ } catch (error) {
1550
+ if ('ENOENT' === error.code) return acc;
1551
+ throw error;
1552
+ }
1553
+ for (let exportName of routeChunkExportNames){
1554
+ if (!source.includes(exportName)) continue;
1555
+ let chunkEntryName = getRouteChunkEntryName(route.id, exportName);
1556
+ manifestChunkNames.add(chunkEntryName), acc[chunkEntryName] = {
1557
+ import: getRouteChunkModuleId(routeFilePath, exportName),
1558
+ html: !1
1559
+ };
1048
1560
  }
1049
- if (source) for (let exportName of routeChunkExportNames)source.includes(exportName) && (acc[getRouteChunkEntryName(route.id, exportName)] = {
1050
- import: getRouteChunkModuleId(routeFilePath, exportName)
1051
- });
1052
1561
  }
1053
1562
  return acc;
1054
- }, {}), routesByServerBundleId = ((buildManifest)=>{
1055
- if (!buildManifest || !('routeIdToServerBundleId' in buildManifest)) return {};
1056
- let routesByServerBundleId = {};
1057
- for (let [routeId, serverBundleId] of Object.entries(buildManifest.routeIdToServerBundleId))for (let route of (routesByServerBundleId[serverBundleId] ??= {}, getRouteBranch(buildManifest.routes, routeId)))routesByServerBundleId[serverBundleId][route.id] = route;
1058
- return routesByServerBundleId;
1059
- })(await getBuildManifest({
1563
+ }, {}), buildManifest = await getBuildManifest({
1060
1564
  reactRouterConfig: resolvedConfigWithRoutes,
1061
1565
  routes,
1062
1566
  rootDirectory: process.cwd()
1063
- })), outputClientPath = resolve(buildDirectory, 'client'), assetsBuildDirectory = relative(process.cwd(), outputClientPath);
1567
+ }), routesByServerBundleId = ((buildManifest, sourceRoutes)=>{
1568
+ if (!buildManifest || !('routeIdToServerBundleId' in buildManifest)) return {};
1569
+ let routesByServerBundleId = {};
1570
+ for (let [routeId, serverBundleId] of Object.entries(buildManifest.routeIdToServerBundleId))for (let route of (routesByServerBundleId[serverBundleId] ??= {}, getRouteBranch(sourceRoutes, routeId)))routesByServerBundleId[serverBundleId][route.id] = route;
1571
+ return routesByServerBundleId;
1572
+ })(buildManifest, routes), serverBuildPlan = (({ routesByServerBundleId, serverBuildFile, defaultEntryName })=>{
1573
+ let serverBuildFileBase = (serverBuildFile || 'index.js').replace(/\.js$/, ''), serverBundleEntries = Object.entries(routesByServerBundleId).filter(([, bundleRoutes])=>!!(bundleRoutes && Object.keys(bundleRoutes).length > 0)).map(([bundleId])=>({
1574
+ bundleId,
1575
+ entryName: `${bundleId}/${serverBuildFileBase}`
1576
+ })), reservedNodeEntryNames = new Set([
1577
+ 'static/js/app',
1578
+ 'static/js/entry.server',
1579
+ defaultEntryName
1580
+ ]);
1581
+ for (let { entryName } of serverBundleEntries){
1582
+ if (reservedNodeEntryNames.has(entryName)) throw Error(`[${PLUGIN_NAME}] Server bundle entry ${JSON.stringify(entryName)} conflicts with a reserved node entry.`);
1583
+ reservedNodeEntryNames.add(entryName);
1584
+ }
1585
+ return {
1586
+ defaultEntryName,
1587
+ entryNames: [
1588
+ defaultEntryName,
1589
+ ...serverBundleEntries.map(({ entryName })=>entryName)
1590
+ ],
1591
+ serverBundleEntries
1592
+ };
1593
+ })({
1594
+ routesByServerBundleId,
1595
+ serverBuildFile,
1596
+ defaultEntryName: devServerBuildEntryName
1597
+ }), { serverBundleEntries } = serverBuildPlan, devRuntime = (({ api, isBuild, buildPlan })=>{
1598
+ let scheduledCssAssetOwnershipReload, state, nextSessionId, closeObservationByServer, isCurrentBinding, applyCloseOutcome, observeClose, identityByCompilation, webIdentityByNodeCompilation;
1599
+ if (isBuild) return {
1600
+ captureWeb () {},
1601
+ createBuildLoader: ()=>()=>Promise.reject(Error(`[${PLUGIN_NAME}] The development server runtime is unavailable during a production build.`))
1602
+ };
1603
+ let lastCssAssetOwnershipReloadAt = 0, reloadAfterCssAssetOwnershipRemoval = !1, sendCssAssetOwnershipReload = ()=>{
1604
+ let binding = sessions.getActiveBinding();
1605
+ binding && (lastCssAssetOwnershipReloadAt = Date.now(), binding.server.sockWrite('full-reload', {
1606
+ path: '*'
1607
+ }));
1608
+ }, scheduleCssAssetOwnershipReload = ()=>{
1609
+ scheduledCssAssetOwnershipReload && clearTimeout(scheduledCssAssetOwnershipReload);
1610
+ let scheduledAt = Date.now();
1611
+ scheduledCssAssetOwnershipReload = setTimeout(()=>{
1612
+ scheduledCssAssetOwnershipReload = void 0, lastCssAssetOwnershipReloadAt > scheduledAt || sendCssAssetOwnershipReload();
1613
+ }, 1000);
1614
+ }, closeBinding = (binding, error)=>{
1615
+ scheduledCssAssetOwnershipReload && (clearTimeout(scheduledCssAssetOwnershipReload), scheduledCssAssetOwnershipReload = void 0), reloadAfterCssAssetOwnershipRemoval = !1;
1616
+ let pair = binding.compilers;
1617
+ pair && (pair.pendingAttempt = void 0, pair.latestCompletedWebIdentity = void 0, pair.latestWebStart = void 0, pair.latestNodeStart = void 0), binding.compilers = void 0, binding.runtime.close(error);
1618
+ var server = binding.server, runtime = binding.runtime;
1619
+ Reflect.get(server, DEV_RUNTIME_KEY) === runtime && Reflect.deleteProperty(server, DEV_RUNTIME_KEY);
1620
+ }, sessions = (state = {
1621
+ status: 'idle'
1622
+ }, nextSessionId = 1, closeObservationByServer = new WeakMap(), isCurrentBinding = (binding)=>('active' === state.status || 'closing' === state.status) && state.binding === binding, applyCloseOutcome = (observation, outcome)=>{
1623
+ observation.outcome = outcome;
1624
+ let { binding } = observation;
1625
+ if (binding) {
1626
+ if (outcome.ok) isCurrentBinding(binding) && ('active' === state.status && closeBinding(binding), state = {
1627
+ status: 'idle'
1628
+ });
1629
+ else ((binding, cause)=>{
1630
+ if (!isCurrentBinding(binding)) return;
1631
+ let error = Error(`[${PLUGIN_NAME}] The previous development server failed to close. Restart the process before retrying because Rsbuild may not have finished tearing down its compiler and watchers.`, {
1632
+ cause
1633
+ });
1634
+ closeBinding(binding, error), state = {
1635
+ status: 'terminal',
1636
+ error
1637
+ };
1638
+ })(binding, outcome.cause);
1639
+ observation.binding = void 0;
1640
+ }
1641
+ }, observeClose = (server)=>{
1642
+ let existing = closeObservationByServer.get(server);
1643
+ if (existing) return existing;
1644
+ let observation = {}, close = server.close.bind(server);
1645
+ return server.close = ()=>{
1646
+ let closePromise;
1647
+ if (observation.promise) return observation.promise;
1648
+ try {
1649
+ closePromise = close();
1650
+ } catch (cause) {
1651
+ closePromise = Promise.reject(cause);
1652
+ }
1653
+ return observation.promise = closePromise, closePromise.then(()=>applyCloseOutcome(observation, {
1654
+ ok: !0
1655
+ }), (cause)=>applyCloseOutcome(observation, {
1656
+ ok: !1,
1657
+ cause
1658
+ })), closePromise;
1659
+ }, closeObservationByServer.set(server, observation), observation;
1660
+ }, {
1661
+ getState: ()=>state,
1662
+ getActiveBinding: ()=>'active' === state.status ? state.binding : void 0,
1663
+ observeClose (server) {
1664
+ observeClose(server);
1665
+ },
1666
+ assertCanStart () {
1667
+ if ('terminal' === state.status) throw state.error;
1668
+ if ('active' === state.status) throw Error(`[${PLUGIN_NAME}] A development server is already active. Await its close() before calling createDevServer() again. If startup failed before returning the server, restart the process before retrying.`);
1669
+ if ('closing' === state.status) throw Error(`[${PLUGIN_NAME}] The previous development server is still closing. Await its close() before calling createDevServer() again.`);
1670
+ },
1671
+ createBinding (server, runtime) {
1672
+ let binding = {
1673
+ id: nextSessionId++,
1674
+ server,
1675
+ runtime
1676
+ };
1677
+ return state = {
1678
+ status: 'active',
1679
+ binding
1680
+ }, binding;
1681
+ },
1682
+ bindCloseObservation (binding) {
1683
+ let observation = observeClose(binding.server);
1684
+ observation.binding = binding, observation.outcome && applyCloseOutcome(observation, observation.outcome);
1685
+ },
1686
+ markClosing (binding) {
1687
+ isCurrentBinding(binding) && (state = {
1688
+ status: 'closing',
1689
+ binding
1690
+ });
1691
+ },
1692
+ terminate (binding, error) {
1693
+ isCurrentBinding(binding) && (closeBinding(binding, error), state = {
1694
+ status: 'terminal',
1695
+ error
1696
+ });
1697
+ }
1698
+ }), compilationIdentities = (identityByCompilation = new WeakMap(), webIdentityByNodeCompilation = new WeakMap(), {
1699
+ getCompilationIdentity (compilation) {
1700
+ let existing = identityByCompilation.get(compilation);
1701
+ if (existing) return existing;
1702
+ let identity = Symbol();
1703
+ return identityByCompilation.set(compilation, identity), identity;
1704
+ },
1705
+ getWebIdentityForNodeCompilation: (compilation)=>webIdentityByNodeCompilation.get(compilation),
1706
+ setWebIdentityForNodeCompilation (compilation, identity) {
1707
+ webIdentityByNodeCompilation.set(compilation, identity);
1708
+ }
1709
+ }), { getCompilationIdentity } = compilationIdentities, flushSettledAttempt = (binding, pair)=>{
1710
+ let pending = pair.pendingAttempt;
1711
+ !pending || sessions.getActiveBinding()?.id !== binding.id || !pair.settledCompilations.has(pending.webCompilation) || !pair.settledCompilations.has(pending.nodeCompilation) || (pair.pendingAttempt = void 0, isLatestStartedCompilation(pending.identity.web, pair.latestWebStart) && isLatestStartedCompilation(pending.identity.node, pair.latestNodeStart) && binding.runtime.finishAttempt(pending.stats, pending.changes, pending.identity).catch((cause)=>{
1712
+ sessions.getActiveBinding()?.id === binding.id && binding.runtime.failAttempt(cause instanceof Error ? cause : Error(String(cause)));
1713
+ }));
1714
+ }, rejectUnsupportedCompiler = (reason)=>{
1715
+ let message = `[${PLUGIN_NAME}] Could not coordinate React Router development output because ${reason}.`;
1716
+ api.logger.warn(message);
1717
+ let binding = sessions.getActiveBinding();
1718
+ if (!binding) return;
1719
+ let error = Error(message);
1720
+ sessions.terminate(binding, error);
1721
+ };
1722
+ return api.modifyRsbuildConfig({
1723
+ order: 'post',
1724
+ handler (config) {
1725
+ let existingSetup = config.server?.setup, setup = existingSetup ? Array.isArray(existingSetup) ? existingSetup : [
1726
+ existingSetup
1727
+ ] : [];
1728
+ return {
1729
+ ...config,
1730
+ server: {
1731
+ ...config.server,
1732
+ setup: [
1733
+ (context)=>{
1734
+ 'dev' === context.action && sessions.observeClose(context.server);
1735
+ },
1736
+ ...setup
1737
+ ]
1738
+ }
1739
+ };
1740
+ }
1741
+ }), api.onBeforeStartDevServer({
1742
+ order: 'pre',
1743
+ async handler ({ server }) {
1744
+ sessions.assertCanStart();
1745
+ let runtime = (({ server, buildPlan, onEvaluationError, onCssAssetOwnershipChanged = ()=>void 0, onRouteManifestChanged = ()=>void 0, onWarning = ()=>void 0 })=>{
1746
+ let nextAttemptId = 1, reloadAfterCssRemoval = !1, state = {
1747
+ kind: 'starting',
1748
+ attemptId: 0,
1749
+ readiness: createDeferred()
1750
+ }, manifestsByCompilation = new WeakMap(), notifyCssAssetOwnershipChanged = (change)=>{
1751
+ try {
1752
+ onCssAssetOwnershipChanged(change);
1753
+ } catch (cause) {
1754
+ let reason = cause instanceof Error ? cause.message : String(cause);
1755
+ onWarning(`[rsbuild-plugin-react-router] Failed to notify the browser after CSS asset ownership changed: ${reason}`);
1756
+ }
1757
+ }, uniqueEntryNames = new Set(buildPlan.entryNames);
1758
+ if (uniqueEntryNames.size !== buildPlan.entryNames.length || !uniqueEntryNames.has(buildPlan.defaultEntryName)) throw Error('[rsbuild-plugin-react-router] The development server build plan must contain unique entries and include its default entry.');
1759
+ let selectBuild = (generation, requestedEntryName)=>{
1760
+ let entryName = requestedEntryName ?? buildPlan.defaultEntryName, build = generation.buildsByEntryName[entryName];
1761
+ if (!build) throw Error(`[rsbuild-plugin-react-router] Committed React Router server build ${JSON.stringify(entryName)} was not found.`);
1762
+ return build;
1763
+ }, getCurrentAttemptId = ()=>'starting' === state.kind ? state.attemptId : 'ready' === state.kind ? state.pendingAttemptId : null, rejectAttempt = (attemptId, error, report)=>{
1764
+ if (getCurrentAttemptId() === attemptId) {
1765
+ if ('starting' === state.kind) {
1766
+ let { readiness } = state;
1767
+ state = {
1768
+ kind: 'failed',
1769
+ attemptId,
1770
+ error
1771
+ }, readiness.reject(error);
1772
+ } else 'ready' === state.kind && (state = {
1773
+ ...state,
1774
+ pendingAttemptId: null
1775
+ });
1776
+ report && onEvaluationError(error);
1777
+ }
1778
+ };
1779
+ return {
1780
+ beginAttempt () {
1781
+ if ('closed' === state.kind) return;
1782
+ let attemptId = nextAttemptId++;
1783
+ state = 'failed' === state.kind ? {
1784
+ kind: 'starting',
1785
+ attemptId,
1786
+ readiness: createDeferred()
1787
+ } : 'starting' === state.kind ? {
1788
+ ...state,
1789
+ attemptId
1790
+ } : {
1791
+ ...state,
1792
+ pendingAttemptId: attemptId
1793
+ };
1794
+ },
1795
+ captureWeb (compilation, manifestsByEntryName) {
1796
+ 'closed' !== state.kind && manifestsByCompilation.set(compilation, structuredClone(manifestsByEntryName));
1797
+ },
1798
+ async finishAttempt (stats, changes, identity) {
1799
+ var previous;
1800
+ let previousEntryNames, nextEntryNames, side, attemptId = getCurrentAttemptId();
1801
+ if (null === attemptId) return;
1802
+ let webStats = getEnvironmentStats(stats, 'web'), nodeStats = getEnvironmentStats(stats, 'node');
1803
+ if (!webStats || !nodeStats) return void rejectAttempt(attemptId, Error('[rsbuild-plugin-react-router] Development compilation did not provide both web and node results.'), !0);
1804
+ if (webStats.compilation.needAdditionalPass || nodeStats.compilation.needAdditionalPass) return;
1805
+ if (webStats.hasErrors() || nodeStats.hasErrors()) return void rejectAttempt(attemptId, Error('[rsbuild-plugin-react-router] The React Router development compilation failed.'), !1);
1806
+ let webCompilation = webStats.compilation, nodeCompilation = nodeStats.compilation, webIdentity = identity.web, nodeIdentity = identity.node;
1807
+ if (!webIdentity || !nodeIdentity) return void rejectAttempt(attemptId, Error('[rsbuild-plugin-react-router] Development compilation identity was unavailable.'), !0);
1808
+ let previous1 = 'ready' === state.kind ? state.committed : void 0, webChanged = !previous1 || previous1.webIdentity !== webIdentity, nodeChanged = !previous1 || previous1.nodeIdentity !== nodeIdentity;
1809
+ if (!webChanged && !nodeChanged) return;
1810
+ let manifestsByEntryName = webChanged ? manifestsByCompilation.get(webCompilation) : previous1?.web.manifestsByEntryName;
1811
+ if (!manifestsByEntryName) return void rejectAttempt(attemptId, Error('[rsbuild-plugin-react-router] The web compilation completed without a matching React Router manifest. Keeping the last-good development build.'), !0);
1812
+ let cssAssetsRemoved = !!previous1 && webChanged && hasRemovedCssAssetOwnership(previous1.web.manifestsByEntryName, manifestsByEntryName), cssAssetsAdded = !!previous1 && webChanged && hasRemovedCssAssetOwnership(manifestsByEntryName, previous1.web.manifestsByEntryName), cssOnlyWebManifestChange = (cssAssetsRemoved || cssAssetsAdded) && (previous = previous1.web.manifestsByEntryName, previousEntryNames = Object.keys(previous).sort(), nextEntryNames = Object.keys(manifestsByEntryName).sort(), previousEntryNames.join('\0') === nextEntryNames.join('\0') && previousEntryNames.every((entryName)=>{
1813
+ let previousManifest = normalizeManifestForCssOwnershipCheck(previous[entryName]), nextManifest = normalizeManifestForCssOwnershipCheck(manifestsByEntryName[entryName]);
1814
+ return JSON.stringify(previousManifest) === JSON.stringify(nextManifest);
1815
+ })), routeManifestMetadataChanged = !!previous1 && webChanged && ((previous, next)=>{
1816
+ let previousEntryNames = Object.keys(previous);
1817
+ if (previousEntryNames.length !== Object.keys(next).length) return !0;
1818
+ for (let entryName of previousEntryNames){
1819
+ let nextManifest = next[entryName];
1820
+ if (!nextManifest) return !0;
1821
+ let previousRoutes = previous[entryName].routes ?? {}, nextRoutes = nextManifest.routes ?? {}, previousRouteIds = Object.keys(previousRoutes);
1822
+ if (previousRouteIds.length !== Object.keys(nextRoutes).length) return !0;
1823
+ for (let routeId of previousRouteIds){
1824
+ let previousRoute = previousRoutes[routeId], nextRoute = nextRoutes[routeId];
1825
+ if (!nextRoute || !hasSameRouteMetadata(previousRoute, nextRoute)) return !0;
1826
+ }
1827
+ }
1828
+ return !1;
1829
+ })(previous1.web.manifestsByEntryName, manifestsByEntryName), reusePreviousNodeBuild = !!previous1 && cssOnlyWebManifestChange;
1830
+ if (nodeChanged && identity.nodeWeb !== webIdentity && !reusePreviousNodeBuild) {
1831
+ let message = '[rsbuild-plugin-react-router] Discarded web and node results from different compiler cycles and kept the last-good build.';
1832
+ if (!previous1) return;
1833
+ onWarning(message), rejectAttempt(attemptId, Error(message), !1);
1834
+ return;
1835
+ }
1836
+ let shouldEvaluateNode = nodeChanged && !reusePreviousNodeBuild;
1837
+ if (!(previous1 && webChanged !== shouldEvaluateNode && !cssOnlyWebManifestChange && (side = webChanged ? 'web-only' : 'node-only', !((changes, dependencies)=>{
1838
+ if (!changes.known || 0 === changes.files.size) return !1;
1839
+ for (let file of changes.files){
1840
+ if (dependencies.files.has(file) || dependencies.missing.has(file)) return !1;
1841
+ for (let directory of dependencies.contexts)if (isWithinDirectory(directory, file)) return !1;
1842
+ }
1843
+ return !0;
1844
+ })(webChanged ? changes.web : changes.node, webChanged ? previous1.nodeDependencies : previous1.web.dependencies) && (onWarning(`[rsbuild-plugin-react-router] Discarded an incomplete ${side} development result and kept the last-good build.`), rejectAttempt(attemptId, Error(`Incomplete ${side} development result.`), !1), 1)))) try {
1845
+ let buildsByEntryName = shouldEvaluateNode ? await evaluateServerBuilds(server, buildPlan.entryNames) : previous1.buildsByEntryName;
1846
+ if (getCurrentAttemptId() !== attemptId) return;
1847
+ let web = webChanged ? {
1848
+ manifestsByEntryName,
1849
+ dependencies: snapshotDependencies(webCompilation)
1850
+ } : previous1.web;
1851
+ if (!((attemptId, committed)=>{
1852
+ if (getCurrentAttemptId() !== attemptId) return !1;
1853
+ if ('starting' === state.kind) {
1854
+ let { readiness } = state;
1855
+ state = {
1856
+ kind: 'ready',
1857
+ committed,
1858
+ pendingAttemptId: null
1859
+ }, readiness.resolve(committed);
1860
+ } else 'ready' === state.kind && (state = {
1861
+ kind: 'ready',
1862
+ committed,
1863
+ pendingAttemptId: null
1864
+ });
1865
+ return !0;
1866
+ })(attemptId, {
1867
+ buildsByEntryName: ((builds, entryNames, manifestsByEntryName)=>{
1868
+ let pinned = {};
1869
+ for (let entryName of entryNames){
1870
+ let build = builds[entryName];
1871
+ if (!build) throw Error(`[rsbuild-plugin-react-router] Expected server build ${JSON.stringify(entryName)} was not evaluated.`);
1872
+ let manifest = manifestsByEntryName[entryName];
1873
+ if (!manifest) throw Error(`[rsbuild-plugin-react-router] Server build ${JSON.stringify(entryName)} has no matching web manifest.`);
1874
+ pinned[entryName] = pinBuildToManifest(entryName, build, manifest);
1875
+ }
1876
+ return pinned;
1877
+ })(buildsByEntryName, buildPlan.entryNames, web.manifestsByEntryName),
1878
+ webIdentity,
1879
+ nodeIdentity: shouldEvaluateNode ? nodeIdentity : previous1.nodeIdentity,
1880
+ web,
1881
+ nodeDependencies: shouldEvaluateNode ? snapshotDependencies(nodeCompilation) : previous1.nodeDependencies
1882
+ })) return;
1883
+ cssAssetsRemoved ? (reloadAfterCssRemoval = !cssAssetsAdded, notifyCssAssetOwnershipChanged('removed')) : cssAssetsAdded && (reloadAfterCssRemoval && notifyCssAssetOwnershipChanged('restored'), reloadAfterCssRemoval = !1), routeManifestMetadataChanged && (()=>{
1884
+ try {
1885
+ onRouteManifestChanged();
1886
+ } catch (cause) {
1887
+ let reason = cause instanceof Error ? cause.message : String(cause);
1888
+ onWarning(`[rsbuild-plugin-react-router] Failed to notify the browser after route manifest metadata changed: ${reason}`);
1889
+ }
1890
+ })();
1891
+ } catch (cause) {
1892
+ rejectAttempt(attemptId, cause instanceof Error ? cause : Error(String(cause)), !0);
1893
+ }
1894
+ },
1895
+ failAttempt (error) {
1896
+ let attemptId = getCurrentAttemptId();
1897
+ null !== attemptId && rejectAttempt(attemptId, error, !1);
1898
+ },
1899
+ load (entryName) {
1900
+ if (entryName && !uniqueEntryNames.has(entryName)) return Promise.reject(Error(`[rsbuild-plugin-react-router] React Router server build ${JSON.stringify(entryName)} is not part of this development server build plan.`));
1901
+ if ('ready' === state.kind) return Promise.resolve(selectBuild(state.committed, entryName));
1902
+ if ('starting' === state.kind) {
1903
+ let selected = state.readiness.promise.then((generation)=>selectBuild(generation, entryName));
1904
+ return selected.catch(()=>void 0), selected;
1905
+ }
1906
+ return Promise.reject(state.error);
1907
+ },
1908
+ close (error) {
1909
+ if ('closed' === state.kind) return;
1910
+ let closeError = error ?? Error('[rsbuild-plugin-react-router] The development server closed before a React Router build was ready.');
1911
+ 'starting' === state.kind && state.readiness.reject(closeError), state = {
1912
+ kind: 'closed',
1913
+ error: closeError
1914
+ };
1915
+ }
1916
+ };
1917
+ })({
1918
+ server,
1919
+ buildPlan,
1920
+ onEvaluationError (error) {
1921
+ sessions.getActiveBinding()?.runtime === runtime && (api.logger.error(error.message), server.sockWrite('errors', {
1922
+ text: [
1923
+ error.message
1924
+ ],
1925
+ html: error.message.replaceAll('&', '&amp;').replaceAll('<', '&lt;').replaceAll('>', '&gt;')
1926
+ }));
1927
+ },
1928
+ onCssAssetOwnershipChanged (change) {
1929
+ sessions.getActiveBinding()?.runtime === runtime && (reloadAfterCssAssetOwnershipRemoval = 'removed' === change, sendCssAssetOwnershipReload());
1930
+ },
1931
+ onRouteManifestChanged () {
1932
+ sessions.getActiveBinding()?.runtime === runtime && server.sockWrite('full-reload', {
1933
+ path: '*'
1934
+ });
1935
+ },
1936
+ onWarning: (message)=>api.logger.warn(message)
1937
+ }), binding = sessions.createBinding(server, runtime);
1938
+ Object.defineProperty(server, DEV_RUNTIME_KEY, {
1939
+ configurable: !0,
1940
+ enumerable: !1,
1941
+ value: runtime
1942
+ }), sessions.bindCloseObservation(binding);
1943
+ }
1944
+ }), api.onCloseDevServer({
1945
+ order: 'pre',
1946
+ handler () {
1947
+ let binding = sessions.getActiveBinding();
1948
+ binding && (closeBinding(binding), sessions.markClosing(binding));
1949
+ }
1950
+ }), api.onBeforeDevCompile({
1951
+ order: 'pre',
1952
+ handler () {
1953
+ let binding = sessions.getActiveBinding(), pair = binding?.compilers;
1954
+ !binding || !pair || hasPendingCompilation(pair) || (pair.pendingAttempt = void 0, binding.runtime.beginAttempt());
1955
+ }
1956
+ }), api.onAfterCreateCompiler(({ compiler })=>{
1957
+ if (!('compilers' in compiler)) return void rejectUnsupportedCompiler('Rsbuild did not create a multi-compiler');
1958
+ let web = compiler.compilers.find((item)=>'web' === item.name), node = compiler.compilers.find((item)=>'node' === item.name);
1959
+ if (!web || !node) return void rejectUnsupportedCompiler('the web or node compiler was missing');
1960
+ let binding = sessions.getActiveBinding();
1961
+ if (!binding) return;
1962
+ let pair = {
1963
+ web,
1964
+ node,
1965
+ settledCompilations: new WeakSet()
1966
+ };
1967
+ binding.compilers = pair;
1968
+ let sessionId = binding.id, runtime = binding.runtime, failCurrentAttempt = (side, error)=>{
1969
+ sessions.getActiveBinding()?.id === sessionId && ('web' === side ? pair.latestWebStart = void 0 : pair.latestNodeStart = void 0, pair.pendingAttempt = void 0, runtime.failAttempt(error));
1970
+ }, beginCompilerAttempt = (side)=>{
1971
+ if (sessions.getActiveBinding()?.id === sessionId && pair[side]?.status !== 'pending') {
1972
+ let attemptAlreadyPending = hasPendingCompilation(pair);
1973
+ pair[side] = {
1974
+ status: 'pending'
1975
+ }, pair.pendingAttempt = void 0, attemptAlreadyPending || runtime.beginAttempt(), 'latestWebStart' === side && reloadAfterCssAssetOwnershipRemoval && (reloadAfterCssAssetOwnershipRemoval = !1, scheduleCssAssetOwnershipReload());
1976
+ }
1977
+ };
1978
+ web.hooks.invalid.tap(`${PLUGIN_NAME}:dev-web-invalid`, ()=>beginCompilerAttempt('latestWebStart')), node.hooks.invalid.tap(`${PLUGIN_NAME}:dev-node-invalid`, ()=>beginCompilerAttempt('latestNodeStart')), web.hooks.done.tap({
1979
+ name: `${PLUGIN_NAME}:dev-web-complete`,
1980
+ stage: -1000
1981
+ }, (stats)=>{
1982
+ sessions.getActiveBinding()?.id === sessionId && (pair.latestCompletedWebIdentity = getCompilationIdentity(stats.compilation));
1983
+ }), web.hooks.thisCompilation.tap(`${PLUGIN_NAME}:dev-web-compilation`, (compilation)=>{
1984
+ sessions.getActiveBinding()?.id === sessionId && (pair.latestWebStart = {
1985
+ status: 'started',
1986
+ identity: getCompilationIdentity(compilation)
1987
+ }, reloadAfterCssAssetOwnershipRemoval && (reloadAfterCssAssetOwnershipRemoval = !1, scheduleCssAssetOwnershipReload()));
1988
+ }), node.hooks.thisCompilation.tap(`${PLUGIN_NAME}:dev-node-web-compilation`, (compilation)=>{
1989
+ sessions.getActiveBinding()?.id === sessionId && (pair.latestNodeStart = {
1990
+ status: 'started',
1991
+ identity: getCompilationIdentity(compilation)
1992
+ }, pair.latestCompletedWebIdentity && compilationIdentities.setWebIdentityForNodeCompilation(compilation, pair.latestCompletedWebIdentity));
1993
+ });
1994
+ let settleCompilation = (stats)=>{
1995
+ sessions.getActiveBinding()?.id === sessionId && (pair.settledCompilations.add(stats.compilation), flushSettledAttempt(binding, pair));
1996
+ };
1997
+ web.hooks.afterDone.tap(`${PLUGIN_NAME}:dev-web-settled`, settleCompilation), node.hooks.afterDone.tap(`${PLUGIN_NAME}:dev-node-settled`, settleCompilation), web.hooks.failed.tap(`${PLUGIN_NAME}:dev-web-failed`, (error)=>failCurrentAttempt('web', error)), node.hooks.failed.tap(`${PLUGIN_NAME}:dev-node-failed`, (error)=>failCurrentAttempt('node', error));
1998
+ }), api.onAfterDevCompile(async ({ stats })=>{
1999
+ let binding = sessions.getActiveBinding(), pair = binding?.compilers;
2000
+ if (!binding || !pair) return;
2001
+ let webStats = getEnvironmentStats(stats, 'web'), nodeStats = getEnvironmentStats(stats, 'node');
2002
+ if (webStats && webStats.compilation.compiler !== pair.web || nodeStats && nodeStats.compilation.compiler !== pair.node) return;
2003
+ let webIdentity = webStats ? getCompilationIdentity(webStats.compilation) : void 0, nodeIdentity = nodeStats ? getCompilationIdentity(nodeStats.compilation) : void 0;
2004
+ if (!isLatestStartedCompilation(webIdentity, pair.latestWebStart) || !isLatestStartedCompilation(nodeIdentity, pair.latestNodeStart)) return;
2005
+ let changes = {
2006
+ web: snapshotDevChangedFiles(pair.web),
2007
+ node: snapshotDevChangedFiles(pair.node)
2008
+ }, identity = {
2009
+ web: webIdentity,
2010
+ node: nodeIdentity,
2011
+ nodeWeb: nodeStats ? compilationIdentities.getWebIdentityForNodeCompilation(nodeStats.compilation) : void 0
2012
+ };
2013
+ webStats && nodeStats ? (pair.pendingAttempt = {
2014
+ stats,
2015
+ changes,
2016
+ identity,
2017
+ webCompilation: webStats.compilation,
2018
+ nodeCompilation: nodeStats.compilation
2019
+ }, flushSettledAttempt(binding, pair)) : await binding.runtime.finishAttempt(stats, changes, identity);
2020
+ }), {
2021
+ captureWeb (compilation, manifestsByEntryName) {
2022
+ let binding = sessions.getActiveBinding();
2023
+ binding?.compilers?.web === compilation.compiler && binding.runtime.captureWeb(compilation, manifestsByEntryName);
2024
+ },
2025
+ createBuildLoader (entryName) {
2026
+ let server = sessions.getActiveBinding()?.server;
2027
+ if (server) return ()=>loadReactRouterServerBuild(server, entryName);
2028
+ let state = sessions.getState();
2029
+ if ('terminal' === state.status) {
2030
+ let { error } = state;
2031
+ return ()=>Promise.reject(error);
2032
+ }
2033
+ return ()=>Promise.reject(Error(`[${PLUGIN_NAME}] The development server runtime is not ready.`));
2034
+ }
2035
+ };
2036
+ })({
2037
+ api,
2038
+ isBuild,
2039
+ buildPlan: serverBuildPlan
2040
+ });
1064
2041
  api.onAfterEnvironmentCompile(({ stats, environment })=>{
1065
- if ('web' === environment.name && (clientStats = stats?.toJson()), pluginOptions.federation && ssr) {
1066
- let serverBuildDir = resolve(buildDirectory, 'server'), clientBuildDir = resolve(buildDirectory, 'client');
2042
+ if ('web' === environment.name && (clientStats = createReactRouterManifestStats(stats?.compilation, manifestChunkNames)), pluginOptions.federation && ssr) {
2043
+ let serverBuildDir = external_pathe_resolve(buildDirectory, 'server'), clientBuildDir = external_pathe_resolve(buildDirectory, 'client');
1067
2044
  if (existsSync(serverBuildDir)) {
1068
- let ssrDir = resolve(clientBuildDir, 'static');
2045
+ let ssrDir = external_pathe_resolve(clientBuildDir, 'static');
1069
2046
  fs_extra.copySync(serverBuildDir, ssrDir);
1070
2047
  }
1071
2048
  }
2049
+ logPerformance && performanceProfiler.flush(environment.name, {
2050
+ compilerLifecycleMs: roundMs(performance.now() - setupStartMs)
2051
+ });
1072
2052
  });
1073
2053
  let prerenderPaths = await resolvePrerenderPaths(prerenderConfig, ssr, routeConfig, {
1074
2054
  logWarning: !0,
1075
2055
  warn: (message)=>api.logger.warn(message)
1076
- }), isPrerenderEnabled = void 0 !== prerenderConfig && !1 !== prerenderConfig, isSpaMode = !ssr && !isPrerenderEnabled, groupRoutesByParentId = (manifest)=>{
1077
- let grouped = {};
1078
- return Object.values(manifest).forEach((route)=>{
1079
- if (!route) return;
1080
- let parentId = route.parentId || '';
1081
- grouped[parentId] || (grouped[parentId] = []), grouped[parentId].push(route);
1082
- }), grouped;
1083
- }, createPrerenderRoutes = (manifest, parentId = '', grouped = groupRoutesByParentId(manifest))=>(grouped[parentId] || []).map((route)=>{
1084
- let common = {
1085
- id: route.id,
1086
- path: route.path
1087
- };
1088
- return route.index ? {
1089
- index: !0,
1090
- ...common
1091
- } : {
1092
- ...common,
1093
- children: createPrerenderRoutes(manifest, route.id, grouped)
1094
- };
1095
- }), normalizePrerenderMatchPath = (path)=>`/${path}/`.replace(/^\/\/+/, '/'), prerenderData = async (handler, prerenderPath, onlyRoutes, clientBuildDir, requestInit)=>{
1096
- let dataRequestPath;
1097
- dataRequestPath = future?.unstable_trailingSlashAwareDataRequests ? prerenderPath.endsWith('/') ? `${prerenderPath}_.data` : `${prerenderPath}.data` : '/' === prerenderPath ? '/_root.data' : `${prerenderPath.replace(/\/$/, '')}.data`;
1098
- let normalizedPath = `${basename}${dataRequestPath}`.replace(/\/\/+/g, '/'), url = new URL(`http://localhost${normalizedPath}`);
1099
- onlyRoutes?.length && url.searchParams.set('_routes', onlyRoutes.join(','));
1100
- let request = new Request(url, requestInit), response = await handler(request), data = await response.text();
1101
- if (200 !== response.status && 202 !== response.status) throw Error(`Prerender (data): Received a ${response.status} status code from \`entry.server.tsx\` while prerendering the \`${prerenderPath}\` path.\n${normalizedPath}`);
1102
- let outputPath = resolve(clientBuildDir, ...normalizedPath.split('/'));
1103
- return await mkdir(dirname(outputPath), {
1104
- recursive: !0
1105
- }), await writeFile(outputPath, data), api.logger.info(`Prerender (data): ${prerenderPath} -> ${relative(process.cwd(), outputPath)}`), data;
1106
- }, prerenderRoute = async (handler, prerenderPath, clientBuildDir, requestInit)=>{
1107
- let normalizedPath = `${basename}${prerenderPath}/`.replace(/\/\/+/g, '/'), request = new Request(`http://localhost${normalizedPath}`, requestInit), response = await handler(request), html = await response.text();
1108
- if (redirectStatusCodes.has(response.status)) {
1109
- let location = response.headers.get('Location'), delay = 2 * (302 === response.status);
1110
- html = `<!doctype html>
1111
- <head>
1112
- <title>Redirecting to: ${location}</title>
1113
- <meta http-equiv="refresh" content="${delay};url=${location}">
1114
- <meta name="robots" content="noindex">
1115
- </head>
1116
- <body>
1117
- \t<a href="${location}">
1118
- Redirecting from <code>${normalizedPath}</code> to <code>${location}</code>
1119
- </a>
1120
- </body>
1121
- </html>`;
1122
- } else if (200 !== response.status) throw Error(`Prerender (html): Received a ${response.status} status code from \`entry.server.tsx\` while prerendering the \`${normalizedPath}\` path.\n` + html);
1123
- let outputPath = resolve(clientBuildDir, ...normalizedPath.split('/'), 'index.html');
1124
- await mkdir(dirname(outputPath), {
1125
- recursive: !0
1126
- }), await writeFile(outputPath, html), api.logger.info(`Prerender (html): ${prerenderPath} -> ${relative(process.cwd(), outputPath)}`);
1127
- }, prerenderResourceRoute = async (handler, prerenderPath, clientBuildDir, requestInit)=>{
1128
- let normalizedPath = `${basename}${prerenderPath}/`.replace(/\/\/+/g, '/').replace(/\/$/g, ''), request = new Request(`http://localhost${normalizedPath}`, requestInit), response = await handler(request), content = Buffer.from(await response.arrayBuffer());
1129
- if (200 !== response.status) throw Error(`Prerender (resource): Received a ${response.status} status code from \`entry.server.tsx\` while prerendering the \`${normalizedPath}\` path.\n` + content.toString('utf8'));
1130
- let outputPath = resolve(clientBuildDir, ...normalizedPath.split('/'));
1131
- await mkdir(dirname(outputPath), {
1132
- recursive: !0
1133
- }), await writeFile(outputPath, content), api.logger.info(`Prerender (resource): ${prerenderPath} -> ${relative(process.cwd(), outputPath)}`);
1134
- }, handleSpaMode = async (handler, build, clientBuildDir)=>{
1135
- let request = new Request(`http://localhost${basename}`, {
1136
- headers: {
1137
- 'X-React-Router-SPA-Mode': 'yes'
1138
- }
1139
- }), response = await handler(request), html = await response.text(), isPrerenderSpaFallback = build.prerender?.includes('/'), filename = isPrerenderSpaFallback ? '__spa-fallback.html' : 'index.html';
1140
- if (200 !== response.status) {
1141
- if (isPrerenderSpaFallback) throw Error(`Prerender: Received a ${response.status} status code from \`entry.server.tsx\` while prerendering your \`${filename}\` file.\n` + html);
1142
- throw Error(`SPA Mode: Received a ${response.status} status code from \`entry.server.tsx\` while prerendering your \`${filename}\` file.\n` + html);
1143
- }
1144
- if (!html.includes('window.__reactRouterContext =') || !html.includes('window.__reactRouterRouteModules =')) throw Error("SPA Mode: Did you forget to include `<Scripts/>` in your root route? Your pre-rendered HTML cannot hydrate without `<Scripts />`.");
1145
- let outputPath = resolve(clientBuildDir, filename);
1146
- await writeFile(outputPath, html);
1147
- let prettyPath = relative(process.cwd(), outputPath);
1148
- build.prerender?.length ? api.logger.info(`Prerender (html): SPA Fallback -> ${prettyPath}`) : api.logger.info(`SPA Mode: Generated ${prettyPath}`);
1149
- }, validateSsrFalsePrerenderExports = async (manifest, prerenderList)=>{
1150
- if (0 === prerenderList.length) return;
1151
- let prerenderRoutes = createPrerenderRoutes(routes), prerenderedRoutes = new Set();
1152
- for (let path of prerenderList){
1153
- let matches = matchRoutes(prerenderRoutes, normalizePrerenderMatchPath(path));
1154
- if (!matches) throw Error(`Unable to prerender path because it does not match any routes: ${path}`);
1155
- matches.forEach((match)=>prerenderedRoutes.add(match.route.id));
1156
- }
1157
- let routeExports = {};
1158
- for (let route of Object.values(routes)){
1159
- let filePath = resolve(appDirectory, route.file);
1160
- routeExports[route.id] = await getRouteModuleExports(filePath);
1161
- }
1162
- let errors = [];
1163
- for (let [routeId, route] of Object.entries(manifest.routes)){
1164
- let exports = routeExports[routeId] ?? [], invalidApis = [];
1165
- if (exports.includes('headers') && invalidApis.push('headers'), exports.includes('action') && invalidApis.push('action'), invalidApis.length > 0 && errors.push(`Prerender: ${invalidApis.length} invalid route export(s) in \`${routeId}\` when pre-rendering with \`ssr:false\`: ${invalidApis.map((api)=>`\`${api}\``).join(', ')}. See https://reactrouter.com/how-to/pre-rendering#invalid-exports for more information.`), !prerenderedRoutes.has(routeId)) {
1166
- exports.includes('loader') && errors.push(`Prerender: 1 invalid route export in \`${routeId}\` when pre-rendering with \`ssr:false\`: \`loader\`. See https://reactrouter.com/how-to/pre-rendering#invalid-exports for more information.`);
1167
- let parentRoute = route.parentId && manifest.routes[route.parentId] ? manifest.routes[route.parentId] : null;
1168
- for(; parentRoute && 'root' !== parentRoute.id;)parentRoute.hasLoader && !parentRoute.hasClientLoader && errors.push(`Prerender: 1 invalid route export in \`${parentRoute.id}\` when pre-rendering with \`ssr:false\`: \`loader\`. See https://reactrouter.com/how-to/pre-rendering#invalid-exports for more information.`), parentRoute = parentRoute.parentId && 'root' !== parentRoute.parentId ? manifest.routes[parentRoute.parentId] : null;
1169
- }
1170
- }
1171
- if (errors.length > 0) throw api.logger.error(errors.join('\n')), Error('Invalid route exports found when prerendering with `ssr:false`');
1172
- };
2056
+ });
1173
2057
  api.onAfterBuild(async ({ environments })=>{
1174
- if (!environments.web) return;
1175
- let serverBuildDir = resolve(buildDirectory, 'server'), defaultServerBuildFile = 'static/js/app.js', configuredServerBuildFile = serverBuildFile || 'index.js', configuredServerBuildPath = resolve(serverBuildDir, configuredServerBuildFile), defaultServerBuildPath = resolve(serverBuildDir, defaultServerBuildFile);
1176
- configuredServerBuildFile !== defaultServerBuildFile && existsSync(defaultServerBuildPath) && !existsSync(configuredServerBuildPath) && (await mkdir(dirname(configuredServerBuildPath), {
1177
- recursive: !0
1178
- }), await fs_extra.copy(defaultServerBuildPath, configuredServerBuildPath));
1179
- let serverBuildPath = existsSync(configuredServerBuildPath) ? configuredServerBuildPath : defaultServerBuildPath, clientBuildDir = resolve(buildDirectory, 'client');
1180
- if (!existsSync(serverBuildPath)) return void console.warn(`[${PLUGIN_NAME}] Server build not found at ${serverBuildPath}. Skipping prerendering.`);
1181
- if (await mkdir(clientBuildDir, {
1182
- recursive: !0
1183
- }), !ssr || isPrerenderEnabled) {
1184
- process.env.IS_RR_BUILD_REQUEST = 'yes';
1185
- let normalizedBuild = normalizeBuildModule(await import(pathToFileURL(serverBuildPath).toString())), build = await resolveBuildExports(normalizedBuild), requestHandler = createRequestHandler(build, 'production');
1186
- if (isPrerenderEnabled) {
1187
- let manifest = await getReactRouterManifestForDev(routes, pluginOptions, clientStats, appDirectory, assetPrefix, routeChunkOptions);
1188
- ssr || await validateSsrFalsePrerenderExports(manifest, prerenderPaths);
1189
- let routeTree = createPrerenderRoutes(routes);
1190
- for (let path of prerenderPaths)if (!matchRoutes(routeTree, normalizePrerenderMatchPath(path))) throw Error(`Unable to prerender path because it does not match any routes: ${path}`);
1191
- prerenderPaths.length > 0 && api.logger.info(`Prerender (html): ${prerenderPaths.length} path(s)...`);
1192
- let buildRoutes = createPrerenderRoutes(build.routes), concurrency = ((prerender)=>{
1193
- if ('object' == typeof prerender && null !== prerender && 'unstable_concurrency' in prerender) {
1194
- let value = prerender?.unstable_concurrency;
1195
- if ('number' == typeof value && Number.isInteger(value) && value > 0) return value;
1196
- }
1197
- return 1;
1198
- })(prerenderConfig), pending = new Set(), enqueue = async (path)=>{
1199
- let matches = matchRoutes(buildRoutes, normalizePrerenderMatchPath(path));
1200
- if (!matches) return;
1201
- let leafRoute = matches[matches.length - 1]?.route, manifestRoute = leafRoute ? build.routes?.[leafRoute.id]?.module : null;
1202
- if (!manifestRoute || manifestRoute.default || manifestRoute.ErrorBoundary) {
1203
- let data;
1204
- matches.some((match)=>{
1205
- let routeId = match.route.id;
1206
- return !!routeId && build.assets?.routes?.[routeId]?.hasLoader;
1207
- }) && (data = await prerenderData(requestHandler, path, null, clientBuildDir)), await prerenderRoute(requestHandler, path, clientBuildDir, data ? {
1208
- headers: {
1209
- 'X-React-Router-Prerender-Data': encodeURI(data)
1210
- }
1211
- } : void 0);
1212
- } else manifestRoute.loader ? (await prerenderData(requestHandler, path, [
1213
- leafRoute.id
1214
- ], clientBuildDir), await prerenderResourceRoute(requestHandler, path, clientBuildDir)) : api.logger.warn(`⚠️ Skipping prerendering for resource route without a loader: ${leafRoute?.id}`);
1215
- };
1216
- for (let path of prerenderPaths){
1217
- let task = enqueue(path);
1218
- pending.add(task), task.finally(()=>pending.delete(task)), pending.size >= concurrency && await Promise.race(pending);
1219
- }
1220
- await Promise.all(pending);
1221
- }
1222
- ssr || await handleSpaMode(requestHandler, build, clientBuildDir);
1223
- }
1224
- if (ssr || (await fs_extra.remove(serverBuildDir), api.logger.info(`[${PLUGIN_NAME}] Removed server build (static deployment)`)), buildEnd) {
1225
- let buildManifest = await getBuildManifest({
1226
- reactRouterConfig: resolvedConfigWithRoutes,
1227
- routes,
1228
- rootDirectory: process.cwd()
1229
- });
1230
- await buildEnd({
1231
- buildManifest,
1232
- reactRouterConfig: resolvedConfigWithRoutes,
1233
- viteConfig: api.getNormalizedConfig()
1234
- });
1235
- }
2058
+ await runReactRouterPrerenderBuild({
2059
+ api,
2060
+ hasWebEnvironment: !!environments.web,
2061
+ buildDirectory,
2062
+ serverBuildFile,
2063
+ ssr,
2064
+ isPrerenderEnabled,
2065
+ prerenderConfig,
2066
+ prerenderPaths,
2067
+ basename,
2068
+ future,
2069
+ routes,
2070
+ latestBrowserManifest,
2071
+ latestBrowserManifestModuleExports,
2072
+ clientStats,
2073
+ pluginOptions,
2074
+ appDirectory,
2075
+ assetPrefix,
2076
+ routeChunkOptions,
2077
+ buildManifest,
2078
+ resolvedConfigWithRoutes,
2079
+ buildEnd
2080
+ });
1236
2081
  });
1237
- let allowedActionOriginsForBuild = !1 === allowedActionOrigins ? void 0 : allowedActionOrigins, vmodTempDir = `rspack-virtual-module-${process.pid}-${Math.random().toString(16).slice(2)}`;
2082
+ let allowedActionOriginsForBuild = !1 === allowedActionOrigins ? void 0 : allowedActionOrigins;
1238
2083
  api.modifyRsbuildConfig(async (config, { mergeRsbuildConfig })=>{
1239
- var publicPath;
2084
+ var existing, publicPath;
1240
2085
  let bundleVirtualModules, bundleManifestModules, vmodPlugin = (publicPath = assetPrefix = normalizeAssetPrefix(config.output?.assetPrefix), bundleVirtualModules = Object.fromEntries(Object.entries(routesByServerBundleId).map(([bundleId, bundleRoutes])=>[
1241
2086
  `virtual/react-router/server-build-${bundleId}`,
1242
2087
  generateServerBuild(bundleRoutes, {
@@ -1256,7 +2101,7 @@ let redirectStatusCodes = new Set([
1256
2101
  ])), bundleManifestModules = Object.fromEntries(Object.entries(routesByServerBundleId).filter(([, bundleRoutes])=>bundleRoutes && Object.keys(bundleRoutes).length > 0).map(([bundleId])=>[
1257
2102
  `virtual/react-router/server-manifest-${bundleId}`,
1258
2103
  'export default {};'
1259
- ])), new RspackVirtualModulePlugin({
2104
+ ])), new rspack.experiments.VirtualModulesPlugin(Object.fromEntries(Object.entries({
1260
2105
  'virtual/react-router/browser-manifest': 'export default {};',
1261
2106
  'virtual/react-router/server-manifest': 'export default {};',
1262
2107
  'virtual/react-router/server-build': generateServerBuild(routes, {
@@ -1274,80 +2119,108 @@ let redirectStatusCodes = new Set([
1274
2119
  }),
1275
2120
  ...bundleVirtualModules,
1276
2121
  ...bundleManifestModules,
1277
- 'virtual/react-router/with-props': `
1278
- import { createElement as h } from "react";
1279
- import { useActionData, useLoaderData, useMatches, useParams, useRouteError } from "react-router";
1280
-
1281
- export function withComponentProps(Component) {
1282
- return function Wrapped() {
1283
- const props = {
1284
- params: useParams(),
1285
- loaderData: useLoaderData(),
1286
- actionData: useActionData(),
1287
- matches: useMatches(),
1288
- };
1289
- return h(Component, props);
1290
- };
1291
- }
1292
-
1293
- export function withHydrateFallbackProps(HydrateFallback) {
1294
- return function Wrapped() {
1295
- const props = {
1296
- params: useParams(),
1297
- };
1298
- return h(HydrateFallback, props);
1299
- };
1300
- }
1301
-
1302
- export function withErrorBoundaryProps(ErrorBoundary) {
1303
- return function Wrapped() {
1304
- const props = {
1305
- params: useParams(),
1306
- loaderData: useLoaderData(),
1307
- actionData: useActionData(),
1308
- error: useRouteError(),
1309
- };
1310
- return h(ErrorBoundary, props);
1311
- };
1312
- }
1313
- `
1314
- }, vmodTempDir)), useAsyncNodeChunkLoading = options.federation && 'commonjs' === resolvedServerOutput, nodeChunkLoading = 'module' === resolvedServerOutput ? 'import' : useAsyncNodeChunkLoading ? 'async-node' : 'require', serverBuildFileBase = (serverBuildFile || 'index.js').replace(/\.js$/, ''), nodeEntries = {
1315
- ...hasServerApp ? {
1316
- 'static/js/app': serverAppPath
1317
- } : {
1318
- 'static/js/app': 'virtual/react-router/server-build'
1319
- },
1320
- 'static/js/entry.server': finalEntryServerPath
1321
- };
1322
- for (let [bundleId, bundleRoutes] of Object.entries(routesByServerBundleId))bundleRoutes && 0 !== Object.keys(bundleRoutes).length && (nodeEntries[`${bundleId}/${serverBuildFileBase}`] = `virtual/react-router/server-build-${bundleId}`);
2122
+ 'virtual/react-router/with-props': generateWithProps()
2123
+ }).map(([moduleId, contents])=>[
2124
+ ((moduleId)=>{
2125
+ if (!moduleId.startsWith(VIRTUAL_MODULE_PREFIX)) throw Error(`Virtual module id must start with ${JSON.stringify(VIRTUAL_MODULE_PREFIX)}: ${moduleId}`);
2126
+ let relativeId = moduleId.slice(VIRTUAL_MODULE_PREFIX.length), segments = relativeId.split('/');
2127
+ if (!relativeId || segments.some((segment)=>!segment || '.' === segment || '..' === segment)) throw Error(`Invalid virtual module id: ${moduleId}`);
2128
+ return `node_modules/${moduleId}.js`;
2129
+ })(moduleId),
2130
+ contents
2131
+ ])))), useAsyncNodeChunkLoading = options.federation && 'commonjs' === resolvedServerOutput, nodeChunkLoading = 'require';
2132
+ 'module' === resolvedServerOutput ? nodeChunkLoading = 'import' : useAsyncNodeChunkLoading && (nodeChunkLoading = 'async-node');
2133
+ let nodeEntries = (({ hasServerApp, isBuild, serverAppPath, entryServerPath, defaultEntryName, serverBundleEntries })=>{
2134
+ let entries = {
2135
+ 'static/js/app': hasServerApp ? serverAppPath : 'virtual/react-router/server-build',
2136
+ 'static/js/entry.server': entryServerPath
2137
+ };
2138
+ for (let { bundleId, entryName } of (hasServerApp && !isBuild && (entries[defaultEntryName] = 'virtual/react-router/server-build'), serverBundleEntries))entries[entryName] = `virtual/react-router/server-build-${bundleId}`;
2139
+ return entries;
2140
+ })({
2141
+ hasServerApp,
2142
+ isBuild,
2143
+ serverAppPath,
2144
+ entryServerPath: finalEntryServerPath,
2145
+ defaultEntryName: devServerBuildEntryName,
2146
+ serverBundleEntries
2147
+ }), guardedLazyCompilation = (({ lazyCompilation, entryClientPath })=>{
2148
+ let eagerPatterns;
2149
+ if (void 0 === lazyCompilation || !1 === lazyCompilation) return lazyCompilation;
2150
+ let options = !0 === lazyCompilation ? {
2151
+ entries: !0,
2152
+ imports: !0
2153
+ } : lazyCompilation, userTest = options.test, isReactRouterHydrationModule = (eagerPatterns = [
2154
+ entryClientPath.replace(/\\/g, '/'),
2155
+ 'virtual/react-router/browser-manifest',
2156
+ BUILD_CLIENT_ROUTE_QUERY_STRING,
2157
+ '?react-router-route'
2158
+ ], (module)=>[
2159
+ module.request,
2160
+ module.userRequest,
2161
+ module.rawRequest,
2162
+ module.resource,
2163
+ module.identifier?.(),
2164
+ module.nameForCondition?.()
2165
+ ].filter((value)=>!!value).some((value)=>{
2166
+ let normalizedValue = value.replace(/\\/g, '/');
2167
+ return eagerPatterns.some((pattern)=>normalizedValue.includes(pattern));
2168
+ }));
2169
+ return {
2170
+ ...options,
2171
+ test (module) {
2172
+ if (isReactRouterHydrationModule(module)) return !1;
2173
+ if (!userTest) return !0;
2174
+ if ('function' == typeof userTest) return userTest(module);
2175
+ let conditionName = module.nameForCondition?.();
2176
+ return !!conditionName && (userTest.lastIndex = 0, userTest.test(conditionName));
2177
+ }
2178
+ };
2179
+ })({
2180
+ lazyCompilation: void 0 === pluginOptions.lazyCompilation ? config.dev?.lazyCompilation : pluginOptions.lazyCompilation,
2181
+ entryClientPath: finalEntryClientPath
2182
+ }), shouldCompactFileSizeReport = isBuild && routeCount >= 256 && (config.performance?.printFileSize === void 0 || !0 === config.performance.printFileSize);
1323
2183
  return mergeRsbuildConfig(config, {
2184
+ ...shouldCompactFileSizeReport ? {
2185
+ performance: {
2186
+ printFileSize: {
2187
+ total: !0,
2188
+ detail: !1,
2189
+ compressed: !1
2190
+ }
2191
+ }
2192
+ } : {},
1324
2193
  output: {
1325
2194
  assetPrefix: config.output?.assetPrefix || '/'
1326
2195
  },
1327
2196
  dev: {
1328
2197
  writeToDisk: !0,
2198
+ ...void 0 === guardedLazyCompilation ? {} : {
2199
+ lazyCompilation: guardedLazyCompilation
2200
+ },
2201
+ watchFiles: (existing = config.dev?.watchFiles, existing ? [
2202
+ ...Array.isArray(existing) ? existing : [
2203
+ existing
2204
+ ],
2205
+ ...routeWatchFiles
2206
+ ] : routeWatchFiles),
1329
2207
  setupMiddlewares: pluginOptions.customServer || !ssr ? [] : [
1330
- (middlewares, server)=>{
1331
- middlewares.push(async (req, res, next)=>{
2208
+ (middlewares)=>{
2209
+ var dependencies;
2210
+ let listenerPromise;
2211
+ middlewares.push((dependencies = {
2212
+ loadBuild: devRuntime.createBuildLoader()
2213
+ }, async (req, res, next)=>{
1332
2214
  try {
1333
- let tryLoadBundle = async (entryName)=>{
1334
- try {
1335
- return await server.environments.node.loadBundle(entryName);
1336
- } catch (error) {
1337
- if (error instanceof Error && error.message.includes("Can't find entry")) return null;
1338
- throw error;
1339
- }
1340
- }, bundle = await tryLoadBundle('static/js/app') ?? await tryLoadBundle('app');
1341
- if (!bundle || !bundle.routes) throw Error('Server bundle not found or invalid');
1342
- let rr = await import("react-router"), nfs = await import("@remix-run/node-fetch-server");
1343
- if ('function' != typeof rr.createRequestHandler) throw Error('[rsbuild-plugin-react-router] Missing `createRequestHandler` export from `react-router`');
1344
- if ('function' != typeof nfs.createRequestListener) throw Error('[rsbuild-plugin-react-router] Missing `createRequestListener` export from `@remix-run/node-fetch-server`');
1345
- let normalizedBuild = normalizeBuildModule(bundle), build = await resolveBuildExports(normalizedBuild), requestHandler = rr.createRequestHandler(build, 'development'), listener = nfs.createRequestListener((request)=>requestHandler(request));
2215
+ let listener = await (listenerPromise ??= (async ()=>{
2216
+ let createRequestHandler = dependencies.createRequestHandler ?? (await import("react-router")).createRequestHandler;
2217
+ return (dependencies.createRequestListener ?? (await import("@remix-run/node-fetch-server")).createRequestListener)(createRequestHandler(dependencies.loadBuild, 'development'));
2218
+ })());
1346
2219
  await listener(req, res);
1347
2220
  } catch (error) {
1348
- console.error('SSR Error:', error), next(error);
2221
+ next(error);
1349
2222
  }
1350
- });
2223
+ }));
1351
2224
  }
1352
2225
  ]
1353
2226
  },
@@ -1360,10 +2233,20 @@ let redirectStatusCodes = new Set([
1360
2233
  },
1361
2234
  environments: {
1362
2235
  web: {
2236
+ ...resolvedConfigWithRoutes.subResourceIntegrity ? {
2237
+ security: {
2238
+ sri: {
2239
+ enable: !0
2240
+ }
2241
+ }
2242
+ } : {},
1363
2243
  source: {
1364
2244
  entry: {
1365
2245
  'entry.client': finalEntryClientPath,
1366
- 'virtual/react-router/browser-manifest': 'virtual/react-router/browser-manifest',
2246
+ 'virtual/react-router/browser-manifest': {
2247
+ import: 'virtual/react-router/browser-manifest',
2248
+ html: !1
2249
+ },
1367
2250
  ...webRouteEntries
1368
2251
  }
1369
2252
  },
@@ -1378,6 +2261,15 @@ let redirectStatusCodes = new Set([
1378
2261
  tools: {
1379
2262
  rspack: {
1380
2263
  name: 'web',
2264
+ module: {
2265
+ rules: [
2266
+ {
2267
+ resourceQuery: urlAssetResourceQuery,
2268
+ exclude: cssUrlAssetExtensions,
2269
+ type: 'asset/resource'
2270
+ }
2271
+ ]
2272
+ },
1381
2273
  ...options.federation ? {
1382
2274
  output: {
1383
2275
  chunkLoading: 'import'
@@ -1395,40 +2287,48 @@ let redirectStatusCodes = new Set([
1395
2287
  module: !0
1396
2288
  },
1397
2289
  optimization: {
2290
+ avoidEntryIife: !0,
1398
2291
  runtimeChunk: 'single'
1399
2292
  }
1400
2293
  }
1401
2294
  }
1402
2295
  },
1403
- ...{
1404
- node: {
1405
- source: {
1406
- entry: nodeEntries
2296
+ node: {
2297
+ source: {
2298
+ entry: nodeEntries
2299
+ },
2300
+ output: {
2301
+ distPath: {
2302
+ root: external_pathe_resolve(buildDirectory, 'server')
1407
2303
  },
1408
- output: {
1409
- distPath: {
1410
- root: resolve(buildDirectory, 'server')
2304
+ target: config.environments?.node?.output?.target || 'node',
2305
+ filename: {
2306
+ js: '[name].js'
2307
+ }
2308
+ },
2309
+ tools: {
2310
+ rspack: {
2311
+ target: options.federation ? 'async-node' : 'node',
2312
+ module: {
2313
+ rules: [
2314
+ {
2315
+ resourceQuery: urlAssetResourceQuery,
2316
+ exclude: cssUrlAssetExtensions,
2317
+ type: 'asset/resource'
2318
+ }
2319
+ ]
1411
2320
  },
1412
- target: config.environments?.node?.output?.target || 'node',
1413
- filename: {
1414
- js: '[name].js'
1415
- }
1416
- },
1417
- tools: {
1418
- rspack: {
1419
- target: options.federation ? 'async-node' : 'node',
1420
- externals: nodeExternals,
1421
- dependencies: [
1422
- 'web'
1423
- ],
1424
- externalsType: resolvedServerOutput,
1425
- output: {
1426
- chunkFormat: resolvedServerOutput,
1427
- chunkLoading: nodeChunkLoading,
1428
- workerChunkLoading: nodeChunkLoading,
1429
- wasmLoading: 'fetch',
1430
- module: 'module' === resolvedServerOutput
1431
- }
2321
+ externals: nodeExternals,
2322
+ dependencies: [
2323
+ 'web'
2324
+ ],
2325
+ externalsType: resolvedServerOutput,
2326
+ output: {
2327
+ chunkFormat: resolvedServerOutput,
2328
+ chunkLoading: nodeChunkLoading,
2329
+ workerChunkLoading: nodeChunkLoading,
2330
+ wasmLoading: 'fetch',
2331
+ module: 'module' === resolvedServerOutput
1432
2332
  }
1433
2333
  }
1434
2334
  }
@@ -1447,400 +2347,236 @@ let redirectStatusCodes = new Set([
1447
2347
  asyncStartup: !0
1448
2348
  });
1449
2349
  }
1450
- })(rspackConfig), 'node' === name && 'module' === resolvedServerOutput) {
1451
- let output = rspackConfig.output, library = output?.library, libraryType = library && 'object' == typeof library && !Array.isArray(library) && 'type' in library ? library.type : void 0;
1452
- output && 'commonjs2' === libraryType && (rspackConfig.output = {
1453
- ...output,
1454
- library: {
1455
- type: 'module'
1456
- }
1457
- });
1458
- }
1459
- return 'web' === name && rspackConfig.plugins && rspackConfig.plugins.push(function(routes, pluginOptions, appDirectory, assetPrefix = '/', routeChunkOptions, options) {
1460
- return {
1461
- apply (compiler) {
1462
- compiler.hooks.emit.tapAsync('ModifyBrowserManifest', async (compilation, callback)=>{
1463
- let sri, stats = compilation.getStats().toJson(), manifest = await getReactRouterManifestForDev(routes, pluginOptions, stats, appDirectory, assetPrefix, routeChunkOptions), virtualManifestPath = 'static/js/virtual/react-router/browser-manifest.js';
1464
- if (compilation.assets[virtualManifestPath]) {
1465
- let newSource = compilation.assets[virtualManifestPath].source().toString().replace(/["'`]PLACEHOLDER["'`]/, jsesc(manifest, {
1466
- es6: !0
1467
- }));
1468
- compilation.assets[virtualManifestPath] = {
1469
- source: ()=>newSource,
1470
- size: ()=>newSource.length,
1471
- map: ()=>({
1472
- version: 3,
1473
- sources: [
1474
- virtualManifestPath
1475
- ],
1476
- names: [],
1477
- mappings: '',
1478
- file: virtualManifestPath,
1479
- sourcesContent: [
1480
- newSource
1481
- ]
1482
- }),
1483
- sourceAndMap: ()=>({
1484
- source: newSource,
1485
- map: {
1486
- version: 3,
1487
- sources: [
1488
- virtualManifestPath
1489
- ],
1490
- names: [],
1491
- mappings: '',
1492
- file: virtualManifestPath,
1493
- sourcesContent: [
1494
- newSource
1495
- ]
1496
- }
1497
- }),
1498
- updateHash: (hash)=>hash.update(newSource),
1499
- buffer: ()=>Buffer.from(newSource)
1500
- };
1501
- }
1502
- if (routeChunkOptions?.isBuild) {
1503
- let entryAssets = stats?.assetsByChunkName?.['entry.client'], entryJsAssets = entryAssets?.filter((asset)=>asset.endsWith('.js')) || [], manifestPath = getReactRouterManifestPath({
1504
- version: manifest.version,
1505
- isBuild: !0,
1506
- entryModulePath: entryJsAssets[0]
1507
- }), manifestSource = `window.__reactRouterManifest=${jsesc(manifest, {
1508
- es6: !0
1509
- })};`;
1510
- compilation.assets[manifestPath] = new rspack.sources.RawSource(manifestSource);
1511
- }
1512
- if (routeChunkOptions?.isBuild && options?.future?.unstable_subResourceIntegrity) for (let asset of (sri = {}, 'function' == typeof compilation.getAssets ? compilation.getAssets() : Object.entries(compilation.assets).map(([name, asset])=>({
1513
- name,
1514
- source: asset
1515
- })))){
1516
- if (!asset.name.endsWith('.js')) continue;
1517
- let source = asset.source.source().toString(), hash = createHash('sha384').update(source).digest('base64');
1518
- sri[combineURLs(assetPrefix, asset.name)] = `sha384-${hash}`;
1519
- }
1520
- options?.onManifest?.(manifest, sri), callback();
1521
- });
1522
- }
1523
- };
1524
- }(routes, pluginOptions, appDirectory, assetPrefix, routeChunkOptions, {
1525
- future,
1526
- onManifest: (manifest, sri)=>{
1527
- let baseServerManifest = {
1528
- ...manifest,
1529
- sri
2350
+ })(rspackConfig), 'node' === name) {
2351
+ let output = rspackConfig.output;
2352
+ if (output) {
2353
+ let library = output.library, libraryOptions = library && 'object' == typeof library && !Array.isArray(library) ? library : {};
2354
+ rspackConfig.output = {
2355
+ ...output,
2356
+ library: {
2357
+ ...libraryOptions,
2358
+ type: 'module' === resolvedServerOutput ? 'module' : 'commonjs2'
2359
+ }
1530
2360
  };
1531
- for (let [bundleId, bundleRoutes] of (latestServerManifest = baseServerManifest, Object.entries(routesByServerBundleId))){
1532
- if (!bundleRoutes) continue;
1533
- let routeIds = new Set(Object.keys(bundleRoutes)), filteredRoutes = Object.fromEntries(Object.entries(manifest.routes).filter(([routeId])=>routeIds.has(routeId)));
1534
- latestServerManifestsByBundleId[bundleId] = {
1535
- ...baseServerManifest,
1536
- routes: filteredRoutes
1537
- };
1538
- }
1539
- }
1540
- })), rspackConfig;
1541
- }
1542
- }
1543
- })), api.processAssets({
1544
- stage: 'additional',
1545
- targets: [
1546
- 'node'
1547
- ]
1548
- }, ({ sources, compilation })=>{
1549
- let packageJsonPath = 'package.json', source = new sources.RawSource(`{"type": "${resolvedServerOutput}"}`);
1550
- compilation.getAsset(packageJsonPath) ? compilation.updateAsset(packageJsonPath, source) : compilation.emitAsset(packageJsonPath, source);
1551
- }), api.transform({
1552
- test: /virtual\/react-router\/(browser|server)-manifest/
1553
- }, async (args)=>{
1554
- if ('web' === args.environment.name) return {
1555
- code: 'window.__reactRouterManifest = "PLACEHOLDER";'
1556
- };
1557
- let bundleMatch = args.resource.match(/virtual\/react-router\/server-manifest(?:-([^?]+))?/), bundleId = bundleMatch?.[1]?.replace(/\\.js$/, ''), manifest = (isBuild && latestServerManifest ? bundleId && latestServerManifestsByBundleId[bundleId] ? latestServerManifestsByBundleId[bundleId] : latestServerManifest : null) ?? await getReactRouterManifestForDev(routes, pluginOptions, clientStats, appDirectory, assetPrefix, routeChunkOptions);
1558
- return {
1559
- code: `export default ${jsesc(manifest, {
1560
- es6: !0
1561
- })};`
1562
- };
1563
- }), api.transform({
1564
- resourceQuery: /__react-router-build-client-route/
1565
- }, async (args)=>{
1566
- let code = await transformToEsm(args.code, args.resourcePath), exportNames = await getExportNames(code), isServer = args.environment?.name === 'node', chunkedExportSet = new Set(!isServer && isBuild && splitRouteModules ? (await detectRouteChunksIfEnabled(routeChunkCache, routeChunkConfig, args.resourcePath, code)).chunkedExports : []), reexports = exportNames.filter((exp)=>!chunkedExportSet.has(exp) && (CLIENT_ROUTE_EXPORTS.includes(exp) || isServer && SERVER_ONLY_ROUTE_EXPORTS.includes(exp))), target = `${args.resourcePath}?react-router-route`;
1567
- return {
1568
- code: `export { ${reexports.join(', ')} } from ${JSON.stringify(target)};`
1569
- };
1570
- }), api.transform({
1571
- resourceQuery: /route-chunk=/
1572
- }, async (args)=>{
1573
- if (args.environment?.name !== 'web') return {
1574
- code: args.code,
1575
- map: null
1576
- };
1577
- let preventEmptyChunkSnippet = (reason)=>`Math.random()<0&&console.log(${JSON.stringify(reason)});`;
1578
- if (!isBuild || !splitRouteModules) return {
1579
- code: preventEmptyChunkSnippet('Split route modules disabled'),
1580
- map: null
1581
- };
1582
- let chunkName = ((id)=>{
1583
- if (!id.includes(routeChunkQueryStringPrefix)) return null;
1584
- let chunkName = id.split(routeChunkQueryStringPrefix)[1].split('&')[0];
1585
- return 'main' === chunkName || routeChunkExportNames.includes(chunkName) ? chunkName : null;
1586
- })(args.resource);
1587
- if (!chunkName) throw Error(`Invalid route chunk name in "${args.resource}"`);
1588
- let transformed = await transformToEsm(args.code, args.resourcePath), chunk = await getRouteChunkIfEnabled(routeChunkCache, routeChunkConfig, args.resourcePath, chunkName, transformed);
1589
- if (enforceSplitRouteModules && 'main' === chunkName && chunk) {
1590
- let exportNames = await getExportNames(chunk);
1591
- validateRouteChunks({
1592
- config: routeChunkConfig,
1593
- id: args.resourcePath,
1594
- valid: {
1595
- clientAction: !exportNames.includes('clientAction'),
1596
- clientLoader: !exportNames.includes('clientLoader'),
1597
- clientMiddleware: !exportNames.includes('clientMiddleware'),
1598
- HydrateFallback: !exportNames.includes('HydrateFallback')
1599
- }
1600
- });
1601
- }
1602
- return {
1603
- code: chunk ?? preventEmptyChunkSnippet(`No ${chunkName} chunk`),
1604
- map: null
1605
- };
1606
- }), api.transform({
1607
- test: /\.[cm]?[jt]sx?$/
1608
- }, async (args)=>{
1609
- if (args.environment?.name !== 'web' || !isBuild || !splitRouteModules || args.resource.includes(BUILD_CLIENT_ROUTE_QUERY_STRING) || args.resource.includes('?react-router-route') || args.resource.includes('route-chunk=') || !routeByFilePath.get(args.resourcePath)) return {
1610
- code: args.code,
1611
- map: null
1612
- };
1613
- let transformed = await transformToEsm(args.code, args.resourcePath), { hasRouteChunks, chunkedExports } = await detectRouteChunksIfEnabled(routeChunkCache, routeChunkConfig, args.resourcePath, transformed);
1614
- if (!hasRouteChunks) return {
1615
- code: args.code,
1616
- map: null
1617
- };
1618
- let sourceExports = await getCachedRouteExports(args.resourcePath), chunkedExportSet = new Set(chunkedExports), mainChunkReexports = sourceExports.filter((name)=>!chunkedExportSet.has(name)).join(', '), chunkBasePath = `./${external_pathe_basename(args.resourcePath)}`;
1619
- return {
1620
- code: [
1621
- mainChunkReexports ? `export { ${mainChunkReexports} } from "${getRouteChunkModuleId(chunkBasePath, 'main')}";` : null,
1622
- ...chunkedExports.map((exportName)=>`export { ${exportName} } from "${getRouteChunkModuleId(chunkBasePath, exportName)}";`)
1623
- ].filter(Boolean).join('\n'),
1624
- map: null
1625
- };
1626
- }), api.transform({
1627
- test: /[\\/]\.server[\\/]|\.server(\.[cm]?[jt]sx?)?$/
1628
- }, async (args)=>{
1629
- if (args.environment?.name !== 'web') return {
1630
- code: args.code,
1631
- map: null
1632
- };
1633
- let relativePath = relative(process.cwd(), args.resourcePath);
1634
- throw Error(`[${PLUGIN_NAME}] Server-only module referenced by client: ${relativePath}`);
1635
- }), api.transform({
1636
- test: /[\\/]\.client[\\/]|\.client(\.[cm]?[jt]sx?)?$/
1637
- }, async (args)=>{
1638
- if (args.environment?.name !== 'node') return {
1639
- code: args.code,
1640
- map: null
1641
- };
1642
- let code = await transformToEsm(args.code, args.resourcePath), { exportNames: directExportNames, exportAllModules } = await getExportNamesAndExportAll(code), exportNames = new Set(directExportNames), unresolvedExportAll = new Set(), visitedModules = new Set(), resolveIndexFile = (dirPath)=>{
1643
- for (let ext of JS_EXTENSIONS){
1644
- let candidate = resolve(dirPath, `index${ext}`);
1645
- if (existsSync(candidate)) try {
1646
- if (statSync(candidate).isFile()) return candidate;
1647
- } catch {
1648
- continue;
1649
- }
1650
- }
1651
- return null;
1652
- }, resolveExportAllModule = (specifier, importerPath)=>{
1653
- if (specifier.startsWith('.') || specifier.startsWith('/')) {
1654
- let resolvedPath = ((basePath)=>{
1655
- if (existsSync(basePath)) try {
1656
- let stats = statSync(basePath);
1657
- if (stats.isFile()) return basePath;
1658
- if (stats.isDirectory()) return resolveIndexFile(basePath);
1659
- } catch {}
1660
- for (let ext of JS_EXTENSIONS){
1661
- let candidate = `${basePath}${ext}`;
1662
- if (existsSync(candidate)) try {
1663
- if (statSync(candidate).isFile()) return candidate;
1664
- } catch {
1665
- continue;
1666
2361
  }
1667
2362
  }
1668
- return resolveIndexFile(basePath);
1669
- })(specifier.startsWith('/') ? specifier : resolve(dirname(importerPath), specifier));
1670
- if (resolvedPath) return resolvedPath;
1671
- }
1672
- try {
1673
- return createRequire(pathToFileURL(importerPath).href).resolve(specifier);
1674
- } catch {
1675
- return null;
1676
- }
1677
- }, collectExportNamesFromModule = async (modulePath)=>{
1678
- if (visitedModules.has(modulePath)) return;
1679
- visitedModules.add(modulePath);
1680
- let source = await readFile(modulePath, 'utf8'), moduleCode = await transformToEsm(source, modulePath), { exportNames: moduleExportNames, exportAllModules: moduleExportAll } = await getExportNamesAndExportAll(moduleCode);
1681
- for (let name of moduleExportNames)'default' !== name && exportNames.add(name);
1682
- for (let nestedSpecifier of moduleExportAll){
1683
- let nestedPath = resolveExportAllModule(nestedSpecifier, modulePath);
1684
- if (!nestedPath) {
1685
- unresolvedExportAll.add(nestedSpecifier);
1686
- continue;
2363
+ return rspackConfig;
1687
2364
  }
1688
- await collectExportNamesFromModule(nestedPath);
1689
2365
  }
1690
- };
1691
- for (let specifier of exportAllModules){
1692
- let resolvedPath = resolveExportAllModule(specifier, args.resourcePath);
1693
- if (!resolvedPath) {
1694
- unresolvedExportAll.add(specifier);
1695
- continue;
2366
+ })), function(api, routes, pluginOptions, appDirectory, assetPrefix = '/', routeChunkOptions, options) {
2367
+ let getAssetPrefix = 'function' == typeof assetPrefix ? assetPrefix : ()=>assetPrefix, manifestChunkNames = options?.manifestChunkNames ?? ((routes, splitRouteModules = !1)=>{
2368
+ let chunkNames = new Set([
2369
+ 'entry.client'
2370
+ ]);
2371
+ for (let route of Object.values(routes))if (chunkNames.add(getRouteEntryName(route)), splitRouteModules && 'root' !== route.id) for (let exportName of routeChunkExportNames)chunkNames.add(getRouteChunkEntryName(route.id, exportName));
2372
+ return chunkNames;
2373
+ })(routes, routeChunkOptions?.splitRouteModules), finalizeSri = !!(routeChunkOptions?.isBuild && (options?.subResourceIntegrity ?? options?.future?.unstable_subResourceIntegrity)), generatedManifests = finalizeSri ? new WeakMap() : void 0;
2374
+ api.processAssets({
2375
+ stage: 'additions',
2376
+ environments: [
2377
+ 'web'
2378
+ ]
2379
+ }, async ({ assets, sources, compilation })=>{
2380
+ let currentAssetPrefix = getAssetPrefix(), stats = createReactRouterManifestStats(compilation, manifestChunkNames), { manifest, moduleExportsByRouteId } = await generateReactRouterManifestForDev(routes, pluginOptions, stats, appDirectory, currentAssetPrefix, routeChunkOptions), manifestForBrowser = finalizeSri ? {
2381
+ ...manifest,
2382
+ sri: !0
2383
+ } : manifest, browserManifestAsset = assets[BROWSER_MANIFEST_ASSET];
2384
+ if (browserManifestAsset) {
2385
+ let newSource = browserManifestAsset.source().toString().replace(/["'`]PLACEHOLDER["'`]/, jsesc(manifestForBrowser, {
2386
+ es6: !0
2387
+ }));
2388
+ compilation.updateAsset(BROWSER_MANIFEST_ASSET, new sources.RawSource(newSource));
1696
2389
  }
1697
- await collectExportNamesFromModule(resolvedPath);
1698
- }
1699
- if (unresolvedExportAll.size > 0) throw Error(`[${PLUGIN_NAME}] Client-only module uses \`export * from\` with unresolvable specifier(s): ${Array.from(unresolvedExportAll).map((spec)=>`\`${spec}\``).join(', ')}. Please explicitly re-export named bindings in \`${relative(process.cwd(), args.resourcePath)}\`.`);
1700
- return {
1701
- code: Array.from(exportNames).map((name)=>'default' === name ? 'export default undefined;' : `export const ${name} = undefined;`).join('\n'),
1702
- map: null
1703
- };
1704
- }), api.transform({
1705
- resourceQuery: /\?react-router-route/
1706
- }, async (args)=>{
1707
- let code, scopeCrawled;
1708
- try {
1709
- code = await transformToEsm(args.code, args.resourcePath);
1710
- } catch (error) {
1711
- throw console.error(args.resourcePath), error;
1712
- }
1713
- if ('web' === args.environment.name && !ssr && isSpaMode) {
1714
- let exportNames = await getExportNames(code), isRootRoute = args.resourcePath === rootRoutePath, invalidServerOnly = exportNames.filter((exp)=>(!isRootRoute || 'loader' !== exp) && SERVER_ONLY_ROUTE_EXPORTS.includes(exp));
1715
- if (invalidServerOnly.length > 0) {
1716
- let list = invalidServerOnly.map((e)=>`\`${e}\``).join(', ');
1717
- throw Error(`SPA Mode: ${invalidServerOnly.length} invalid route export(s) in \`${relative(process.cwd(), args.resourcePath)}\`: ${list}. See https://reactrouter.com/how-to/spa for more information.`);
2390
+ if (routeChunkOptions?.isBuild) {
2391
+ let entryAssets = stats?.assetsByChunkName?.['entry.client'], entryJsAssets = entryAssets?.filter((asset)=>asset.endsWith('.js')) || [], manifestPath = getReactRouterManifestPath({
2392
+ version: manifest.version,
2393
+ isBuild: !0,
2394
+ entryModulePath: entryJsAssets[0]
2395
+ }), manifestSource = `window.__reactRouterManifest=${jsesc(manifestForBrowser, {
2396
+ es6: !0
2397
+ })};`, source = new sources.RawSource(manifestSource);
2398
+ compilation.getAsset(manifestPath) ? compilation.updateAsset(manifestPath, source) : compilation.emitAsset(manifestPath, source);
1718
2399
  }
1719
- if (!isRootRoute && exportNames.includes('HydrateFallback')) throw Error(`SPA Mode: Invalid \`HydrateFallback\` export found in \`${relative(process.cwd(), args.resourcePath)}\`. \`HydrateFallback\` is only permitted on the root route in SPA Mode. See https://reactrouter.com/how-to/spa for more information.`);
1720
- }
1721
- let defaultExportMatch = code.match(/\n\s{0,}([\w\d_]+)\sas default,?/);
1722
- defaultExportMatch && 'number' == typeof defaultExportMatch.index && (code = code.slice(0, defaultExportMatch.index) + code.slice(defaultExportMatch.index + defaultExportMatch[0].length) + `\nexport default ${defaultExportMatch[1]};`);
1723
- let ast = parse(code, {
1724
- sourceType: 'module'
2400
+ generatedManifests ? generatedManifests.set(compilation, {
2401
+ manifest,
2402
+ moduleExportsByRouteId,
2403
+ manifestStats: stats,
2404
+ assetPrefix: currentAssetPrefix
2405
+ }) : options?.onManifest?.(manifest, void 0, moduleExportsByRouteId, {
2406
+ compilation,
2407
+ manifestStats: stats
2408
+ });
2409
+ }), generatedManifests && api.processAssets({
2410
+ stage: 'report',
2411
+ environments: [
2412
+ 'web'
2413
+ ]
2414
+ }, ({ compilation })=>{
2415
+ let generatedManifest = generatedManifests.get(compilation);
2416
+ if (!generatedManifest) return;
2417
+ generatedManifests.delete(compilation);
2418
+ let sri = ((stats, compilation, assetPrefix = '/')=>{
2419
+ let sri = {};
2420
+ for (let asset of stats?.assets ?? [])addIntegrity(sri, assetPrefix, asset.name, asset.integrity);
2421
+ if ('function' == typeof compilation?.getAssets) for (let asset of compilation.getAssets())addIntegrity(sri, assetPrefix, asset.name, asset.info?.integrity);
2422
+ return Object.keys(sri).length > 0 ? sri : void 0;
2423
+ })(void 0, compilation, generatedManifest.assetPrefix) ?? !0;
2424
+ options?.onManifest?.({
2425
+ ...generatedManifest.manifest,
2426
+ sri
2427
+ }, sri, generatedManifest.moduleExportsByRouteId, {
2428
+ compilation,
2429
+ manifestStats: generatedManifest.manifestStats
2430
+ });
1725
2431
  });
1726
- if ('web' === args.environment.name) {
1727
- var exportsToRemove = [
1728
- ...SERVER_ONLY_ROUTE_EXPORTS
1729
- ];
1730
- let previouslyReferencedIdentifiers = findReferencedIdentifiers(ast), exportsFiltered = !1, markedForRemoval = new Set(), removedExportLocalNames = new Set();
1731
- if (traverse(ast, {
1732
- ExportDeclaration (path) {
1733
- if ('ExportNamedDeclaration' === path.node.type) {
1734
- if (path.node.specifiers.length && (path.node.specifiers = path.node.specifiers.filter((specifier)=>!('ExportSpecifier' === specifier.type && 'Identifier' === specifier.exported.type && exportsToRemove.includes(specifier.exported.name)) || (exportsFiltered = !0, specifier.local && 'Identifier' === specifier.local.type && specifier.local.name !== specifier.exported.name && removedExportLocalNames.add(specifier.local.name), !1)), 0 === path.node.specifiers.length && markedForRemoval.add(path)), path.node.declaration?.type === 'VariableDeclaration') {
1735
- let declaration = path.node.declaration;
1736
- declaration.declarations = declaration.declarations.filter((declaration)=>'Identifier' === declaration.id.type && exportsToRemove.includes(declaration.id.name) ? (exportsFiltered = !0, !1) : (('ArrayPattern' === declaration.id.type || 'ObjectPattern' === declaration.id.type) && function validateDestructuredExports(id, exportsToRemove) {
1737
- if ('ArrayPattern' === id.type) {
1738
- for (let element of id.elements)if (element) {
1739
- if ('Identifier' === element.type && exportsToRemove.includes(element.name)) throw invalidDestructureError(element.name);
1740
- if ('RestElement' === element.type && 'Identifier' === element.argument.type && exportsToRemove.includes(element.argument.name)) throw invalidDestructureError(element.argument.name);
1741
- ('ArrayPattern' === element.type || 'ObjectPattern' === element.type) && validateDestructuredExports(element, exportsToRemove);
1742
- }
1743
- }
1744
- if ('ObjectPattern' === id.type) {
1745
- for (let property of id.properties)if (property) {
1746
- if ('ObjectProperty' === property.type && 'Identifier' === property.key.type) {
1747
- if ('Identifier' === property.value.type && exportsToRemove.includes(property.value.name)) throw invalidDestructureError(property.value.name);
1748
- ('ArrayPattern' === property.value.type || 'ObjectPattern' === property.value.type) && validateDestructuredExports(property.value, exportsToRemove);
1749
- }
1750
- if ('RestElement' === property.type && 'Identifier' === property.argument.type && exportsToRemove.includes(property.argument.name)) throw invalidDestructureError(property.argument.name);
1751
- }
1752
- }
1753
- }(declaration.id, exportsToRemove), !0)), 0 === declaration.declarations.length && markedForRemoval.add(path);
1754
- }
1755
- if (path.node.declaration?.type === 'FunctionDeclaration') {
1756
- let id = path.node.declaration.id;
1757
- id && exportsToRemove.includes(id.name) && markedForRemoval.add(path);
1758
- }
1759
- if (path.node.declaration?.type === 'ClassDeclaration') {
1760
- let id = path.node.declaration.id;
1761
- id && exportsToRemove.includes(id.name) && markedForRemoval.add(path);
1762
- }
1763
- }
1764
- 'ExportDefaultDeclaration' === path.node.type && exportsToRemove.includes('default') && (markedForRemoval.add(path), path.node.declaration && ('Identifier' === path.node.declaration.type ? removedExportLocalNames.add(path.node.declaration.name) : ('FunctionDeclaration' === path.node.declaration.type || 'ClassDeclaration' === path.node.declaration.type) && path.node.declaration.id && removedExportLocalNames.add(path.node.declaration.id.name)));
1765
- }
1766
- }), traverse(ast, {
1767
- ExpressionStatement (path) {
1768
- if (!path.parentPath.isProgram()) return;
1769
- let expr = path.node.expression;
1770
- if ('AssignmentExpression' !== expr.type) return;
1771
- let left = expr.left;
1772
- 'MemberExpression' === left.type && 'Identifier' === left.object.type && (exportsToRemove.includes(left.object.name) || removedExportLocalNames.has(left.object.name)) && markedForRemoval.add(path);
2432
+ }(api, routes, pluginOptions, appDirectory, ()=>assetPrefix, routeChunkOptions, {
2433
+ subResourceIntegrity: resolvedConfigWithRoutes.subResourceIntegrity,
2434
+ future,
2435
+ manifestChunkNames,
2436
+ onManifest: (manifest, sri, moduleExportsByRouteId, context)=>{
2437
+ var compilation;
2438
+ return compilation = context.compilation, void performanceProfiler.recordSync('web', 'manifest:stage', 'virtual/react-router/browser-manifest', ()=>{
2439
+ latestBrowserManifest = manifest, latestBrowserManifestModuleExports = moduleExportsByRouteId;
2440
+ let baseServerManifest = {
2441
+ ...manifest,
2442
+ sri: sri
2443
+ };
2444
+ latestServerManifest = baseServerManifest;
2445
+ let manifestsByEntryName = {
2446
+ [devServerBuildEntryName]: baseServerManifest
2447
+ };
2448
+ for (let { bundleId, entryName } of serverBundleEntries){
2449
+ let bundleRoutes = routesByServerBundleId[bundleId];
2450
+ if (!bundleRoutes) continue;
2451
+ let routeIds = new Set(Object.keys(bundleRoutes)), filteredRoutes = Object.fromEntries(Object.entries(manifest.routes).filter(([routeId])=>routeIds.has(routeId))), bundleManifest = {
2452
+ ...baseServerManifest,
2453
+ routes: filteredRoutes
2454
+ };
2455
+ latestServerManifestsByBundleId[bundleId] = bundleManifest, manifestsByEntryName[entryName] = bundleManifest;
1773
2456
  }
1774
- }), markedForRemoval.size > 0 || exportsFiltered) {
1775
- for (let path of markedForRemoval)path.remove();
1776
- deadCodeElimination(ast, previouslyReferencedIdentifiers);
1777
- }
1778
- }
1779
- let hocs = [];
1780
- function getHocUid(path, hocName) {
1781
- let uid = path.scope.generateUidIdentifier(hocName);
1782
- return hocs.push([
1783
- hocName,
1784
- uid
1785
- ]), uid;
2457
+ isBuild || devRuntime.captureWeb(compilation, manifestsByEntryName);
2458
+ });
1786
2459
  }
1787
- return traverse(ast, {
1788
- ExportDeclaration (path) {
1789
- if (path.isExportDefaultDeclaration()) {
1790
- let declaration = path.get('declaration'), expr = declaration.isExpression() ? declaration.node : declaration.isFunctionDeclaration() ? toFunctionExpression(declaration.node) : void 0;
1791
- if (expr) {
1792
- let uid = getHocUid(path, 'withComponentProps');
1793
- declaration.replaceWith(callExpression(uid, [
1794
- expr
1795
- ]));
1796
- }
1797
- return;
1798
- }
1799
- if (path.isExportNamedDeclaration()) {
1800
- let decl = path.get('declaration');
1801
- if (decl.isVariableDeclaration()) return void decl.get('declarations').forEach((varDeclarator)=>{
1802
- let id = varDeclarator.get('id'), init = varDeclarator.get('init'), expr = init.node;
1803
- if (!expr || !id.isIdentifier()) return;
1804
- let { name } = id.node;
1805
- if (!isNamedComponentExport(name)) return;
1806
- let uid = getHocUid(path, `with${name}Props`);
1807
- init.replaceWith(callExpression(uid, [
1808
- expr
1809
- ]));
1810
- });
1811
- if (decl.isFunctionDeclaration()) {
1812
- let { id } = decl.node;
1813
- if (!id) return;
1814
- let { name } = id;
1815
- if (!isNamedComponentExport(name)) return;
1816
- let uid = getHocUid(path, `with${name}Props`);
1817
- decl.replaceWith(variableDeclaration('const', [
1818
- types_variableDeclarator(types_identifier(name), callExpression(uid, [
1819
- toFunctionExpression(decl.node)
1820
- ]))
1821
- ]));
1822
- }
1823
- }
1824
- }
1825
- }), hocs.length > 0 && ast.program.body.unshift(importDeclaration(hocs.map(([name, identifier])=>importSpecifier(identifier, types_identifier(name))), stringLiteral('virtual/react-router/with-props'))), 'web' === args.environment.name && (scopeCrawled = !1, traverse(ast, {
1826
- Program (path) {
1827
- scopeCrawled || (path.scope.crawl(), scopeCrawled = !0);
2460
+ }), (({ api, resolvedServerOutput, performanceProfiler, getLatestServerManifest, getLatestServerManifestByBundleId, routes, pluginOptions, getClientStats, appDirectory, getAssetPrefix, routeChunkOptions, routeTransformExecutor, routeByFilePath, routeChunkConfig, isBuild, splitRouteModules, ssr, isSpaMode, rootRoutePath })=>{
2461
+ let transformRouteModule = async (args)=>performanceProfiler.record(args.environment?.name, 'route:module', args.resource, async ()=>routeTransformExecutor.run({
2462
+ kind: 'routeModule',
2463
+ code: args.code,
2464
+ resource: args.resource,
2465
+ resourcePath: args.resourcePath,
2466
+ environmentName: args.environment.name,
2467
+ sourceMaps: isSourceMapEnabled(args.environment.config.output.sourceMap),
2468
+ ssr,
2469
+ isBuild,
2470
+ isSpaMode,
2471
+ rootRoutePath
2472
+ }));
2473
+ api.processAssets({
2474
+ stage: 'additional',
2475
+ targets: [
2476
+ 'node'
2477
+ ]
2478
+ }, ({ sources, compilation })=>{
2479
+ let packageJsonPath = 'package.json', source = new sources.RawSource(`{"type": "${resolvedServerOutput}"}`);
2480
+ compilation.getAsset(packageJsonPath) ? compilation.updateAsset(packageJsonPath, source) : compilation.emitAsset(packageJsonPath, source);
2481
+ }), api.transform({
2482
+ test: /virtual\/react-router\/(browser|server)-manifest/
2483
+ }, async (args)=>performanceProfiler.record(args.environment?.name, 'manifest:transform', args.resource, async ()=>{
2484
+ if ('web' === args.environment.name) return {
2485
+ code: 'window.__reactRouterManifest = "PLACEHOLDER";'
2486
+ };
2487
+ let bundleMatch = args.resource.match(/virtual\/react-router\/server-manifest(?:-([^?]+))?/), bundleId = bundleMatch?.[1]?.replace(/\.js$/, ''), latestServerManifest = getLatestServerManifest(), manifest = (latestServerManifest ? (bundleId && getLatestServerManifestByBundleId(bundleId)) ?? latestServerManifest : null) ?? await getReactRouterManifestForDev(routes, pluginOptions, getClientStats(), appDirectory, getAssetPrefix(), routeChunkOptions);
2488
+ return {
2489
+ code: `export default ${jsesc(manifest, {
2490
+ es6: !0
2491
+ })};`
2492
+ };
2493
+ })), api.transform({
2494
+ resourceQuery: /__react-router-build-client-route/
2495
+ }, async (args)=>performanceProfiler.record(args.environment?.name, 'route:client-entry', args.resource, async ()=>routeTransformExecutor.run({
2496
+ kind: 'routeClientEntry',
2497
+ code: args.code,
2498
+ resourcePath: args.resourcePath,
2499
+ environmentName: args.environment?.name,
2500
+ isBuild,
2501
+ routeChunkConfig
2502
+ }))), api.transform({
2503
+ resourceQuery: /route-chunk=/,
2504
+ environments: [
2505
+ 'web'
2506
+ ]
2507
+ }, async (args)=>performanceProfiler.record(args.environment?.name, 'route:chunk', args.resource, async ()=>routeTransformExecutor.run({
2508
+ kind: 'routeChunk',
2509
+ code: args.code,
2510
+ resource: args.resource,
2511
+ resourcePath: args.resourcePath,
2512
+ isBuild,
2513
+ routeChunkConfig
2514
+ }))), isBuild && splitRouteModules && api.transform({
2515
+ test: (path)=>routeByFilePath.has(path),
2516
+ resourceQuery: {
2517
+ not: /__react-router-build-client-route|react-router-route|route-chunk=/
1828
2518
  },
1829
- ImportDeclaration (path) {
1830
- if (0 !== path.node.specifiers.length) {
1831
- for (let specifierPath of path.get('specifiers')){
1832
- let local = specifierPath.node.local, binding = local ? path.scope.getBinding(local.name) : null;
1833
- binding && binding.referenced || specifierPath.remove();
1834
- }
1835
- 0 === path.node.specifiers.length && path.remove();
1836
- }
1837
- }
1838
- })), generate(ast, {
1839
- sourceMaps: !0,
1840
- filename: args.resource,
1841
- sourceFileName: args.resourcePath
1842
- });
2519
+ environments: [
2520
+ 'web'
2521
+ ]
2522
+ }, async (args)=>performanceProfiler.record(args.environment?.name, 'route:split-exports', args.resource, async ()=>routeTransformExecutor.run({
2523
+ kind: 'splitRouteExports',
2524
+ code: args.code,
2525
+ resourcePath: args.resourcePath,
2526
+ routeChunkConfig
2527
+ }))), api.transform({
2528
+ test: /[\\/]\.server[\\/]|\.server(\.[cm]?[jt]sx?)?$/,
2529
+ environments: [
2530
+ 'web'
2531
+ ]
2532
+ }, async (args)=>performanceProfiler.record(args.environment?.name, 'module:server-only-guard', args.resource, async ()=>{
2533
+ let relativePath = relative(process.cwd(), args.resourcePath);
2534
+ throw Error(`[${PLUGIN_NAME}] Server-only module referenced by client: ${relativePath}`);
2535
+ })), api.transform({
2536
+ test: /[\\/]\.client[\\/]|\.client(\.[cm]?[jt]sx?)?$/,
2537
+ environments: [
2538
+ 'node'
2539
+ ]
2540
+ }, async (args)=>performanceProfiler.record(args.environment?.name, 'module:client-only-stub', args.resource, async ()=>routeTransformExecutor.run({
2541
+ kind: 'clientOnlyStub',
2542
+ code: args.code,
2543
+ resourcePath: args.resourcePath,
2544
+ resolveExportAllModule: 'function' == typeof args.resolve ? createBundlerRouteExportResolver(args.resolve) : void 0
2545
+ }))), api.transform({
2546
+ resourceQuery: /\?react-router-route/,
2547
+ order: 'post'
2548
+ }, transformRouteModule), api.transform({
2549
+ test: (path)=>routeByFilePath.has(path),
2550
+ resourceQuery: {
2551
+ not: /__react-router-build-client-route|react-router-route|route-chunk=/
2552
+ },
2553
+ order: 'post'
2554
+ }, transformRouteModule);
2555
+ })({
2556
+ api,
2557
+ resolvedServerOutput,
2558
+ performanceProfiler,
2559
+ getLatestServerManifest: ()=>latestServerManifest,
2560
+ getLatestServerManifestByBundleId: (bundleId)=>latestServerManifestsByBundleId[bundleId],
2561
+ routes,
2562
+ pluginOptions,
2563
+ getClientStats: ()=>clientStats,
2564
+ appDirectory,
2565
+ getAssetPrefix: ()=>assetPrefix,
2566
+ routeChunkOptions,
2567
+ routeTransformExecutor,
2568
+ routeByFilePath,
2569
+ routeChunkConfig: {
2570
+ splitRouteModules,
2571
+ appDirectory,
2572
+ rootRouteFile
2573
+ },
2574
+ isBuild,
2575
+ splitRouteModules: !!splitRouteModules,
2576
+ ssr,
2577
+ isSpaMode,
2578
+ rootRoutePath
1843
2579
  });
1844
2580
  }
1845
2581
  });
1846
- export { pluginReactRouter };
2582
+ export { loadReactRouterServerBuild, pluginReactRouter, resolveReactRouterServerBuild };