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.
- package/README.md +185 -204
- package/dist/451.js +1087 -0
- package/dist/bounded-cache.d.ts +1 -0
- package/dist/build-manifest.d.ts +1 -1
- package/dist/build-output-transforms.d.ts +30 -0
- package/dist/concurrency.d.ts +2 -0
- package/dist/config-imports.d.ts +3 -0
- package/dist/constants.d.ts +3 -0
- package/dist/dev-generation.d.ts +25 -0
- package/dist/dev-runtime-artifacts.d.ts +39 -0
- package/dist/dev-runtime-compilation.d.ts +32 -0
- package/dist/dev-runtime-controller.d.ts +14 -0
- package/dist/dev-runtime-session.d.ts +34 -0
- package/dist/dev-server.d.ts +11 -2
- package/dist/export-utils.d.ts +15 -7
- package/dist/index.cjs +3050 -1244
- package/dist/index.d.ts +4 -1
- package/dist/index.js +2015 -1279
- package/dist/lazy-compilation.d.ts +5 -0
- package/dist/manifest.d.ts +32 -9
- package/dist/modify-browser-manifest.d.ts +30 -13
- package/dist/parallel-route-transform-protocol.d.ts +25 -0
- package/dist/parallel-route-transform-worker.d.ts +1 -0
- package/dist/parallel-route-transform-worker.js +38 -0
- package/dist/parallel-route-transforms.d.ts +14 -0
- package/dist/performance.d.ts +26 -0
- package/dist/plugin-utils.d.ts +2 -12
- package/dist/prerender-build.d.ts +32 -0
- package/dist/prerender.d.ts +28 -2
- package/dist/react-router-config.d.ts +8 -1
- package/dist/route-artifacts.d.ts +33 -0
- package/dist/route-ast.d.ts +21 -0
- package/dist/route-chunks.d.ts +9 -1
- package/dist/route-component-transform.d.ts +5 -0
- package/dist/route-export-pruning.d.ts +6 -0
- package/dist/route-export-resolution.d.ts +5 -0
- package/dist/route-transform-tasks.d.ts +47 -0
- package/dist/route-watch.d.ts +27 -0
- package/dist/server-build-plan.d.ts +22 -0
- package/dist/server-utils.d.ts +3 -2
- package/dist/templates/entry.server.cjs +3 -3
- package/dist/templates/entry.server.js +3 -3
- package/dist/typegen.d.ts +2 -0
- package/dist/types.d.ts +30 -12
- package/dist/virtual-modules.d.ts +2 -0
- package/dist/warnings/warn-on-client-source-maps.d.ts +1 -0
- package/dist/yuku.d.ts +15 -0
- package/package.json +22 -19
- package/src/bounded-cache.ts +18 -0
- package/src/build-manifest.ts +168 -0
- package/src/build-output-transforms.ts +273 -0
- package/src/concurrency.ts +34 -0
- package/src/config-imports.ts +45 -0
- package/src/constants.ts +91 -0
- package/src/dev-generation.ts +700 -0
- package/src/dev-runtime-artifacts.ts +207 -0
- package/src/dev-runtime-compilation.ts +92 -0
- package/src/dev-runtime-controller.ts +462 -0
- package/src/dev-runtime-session.ts +184 -0
- package/src/dev-server.ts +58 -0
- package/src/export-utils.ts +219 -0
- package/src/index.ts +1025 -0
- package/src/lazy-compilation.ts +94 -0
- package/src/manifest.ts +480 -0
- package/src/modify-browser-manifest.ts +245 -0
- package/src/parallel-route-transform-protocol.ts +35 -0
- package/src/parallel-route-transform-worker.ts +82 -0
- package/src/parallel-route-transforms.ts +332 -0
- package/src/performance.ts +254 -0
- package/src/plugin-utils.ts +82 -0
- package/src/prerender-build.ts +623 -0
- package/src/prerender.ts +367 -0
- package/src/react-router-config.ts +220 -0
- package/src/route-artifacts.ts +155 -0
- package/src/route-ast.ts +163 -0
- package/src/route-chunks.ts +857 -0
- package/src/route-component-transform.ts +314 -0
- package/src/route-config.ts +106 -0
- package/src/route-export-pruning.ts +668 -0
- package/src/route-export-resolution.ts +329 -0
- package/src/route-transform-tasks.ts +249 -0
- package/src/route-watch.ts +322 -0
- package/src/server-build-plan.ts +91 -0
- package/src/server-utils.ts +210 -0
- package/src/ssr-externals.ts +59 -0
- package/src/templates/context.ts +12 -0
- package/src/templates/entry.client.tsx +12 -0
- package/src/templates/entry.server.tsx +76 -0
- package/src/typegen.ts +49 -0
- package/src/types.ts +82 -0
- package/src/validation/validate-plugin-order.ts +76 -0
- package/src/virtual-modules.ts +30 -0
- package/src/warnings/warn-on-client-source-maps.ts +96 -0
- package/src/yuku.ts +67 -0
- package/dist/0~rslib-runtime.js +0 -16
- package/dist/babel.d.ts +0 -8
package/dist/index.js
CHANGED
|
@@ -1,68 +1,25 @@
|
|
|
1
|
-
|
|
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
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
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 {
|
|
17
|
-
import
|
|
18
|
-
import {
|
|
19
|
-
import
|
|
20
|
-
|
|
21
|
-
|
|
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(`${
|
|
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
|
-
])
|
|
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
|
|
129
|
-
|
|
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
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
for (let
|
|
136
|
-
let
|
|
137
|
-
if (
|
|
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
|
-
|
|
100
|
+
throw Error(`[rsbuild-plugin-react-router] ${source} did not contain a valid React Router ServerBuild.`);
|
|
140
101
|
}
|
|
141
|
-
function
|
|
142
|
-
return
|
|
102
|
+
function resolveReactRouterServerBuild(buildModule) {
|
|
103
|
+
return resolveServerBuildModule(buildModule, 'Imported module');
|
|
143
104
|
}
|
|
144
|
-
let normalizePath = (value)=>value.replace(/\/\/+/g, '/').replace(/(.+)\/$/, '$1'),
|
|
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
|
-
},
|
|
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
|
-
|
|
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
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
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
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
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
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
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
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
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
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
}
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
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
|
-
|
|
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
|
-
|
|
558
|
-
|
|
559
|
-
});
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
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
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
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
|
-
|
|
586
|
-
|
|
587
|
-
|
|
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
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
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 = "AGFzbQEAAAABKwhgAX8Bf2AEf39/fwBgAAF/YAAAYAF/AGADf39/AX9gAn9/AX9gA39/fwADMTAAAQECAgICAgICAgICAgICAgICAgIAAwMDBAQAAAUAAAAAAAMDAwAGAAAABwAGAgUEBQFwAQEBBQMBAAEGDwJ/AUHA8gALfwBBwPIACwd6FQZtZW1vcnkCAAJzYQAAAWUAAwJpcwAEAmllAAUCc3MABgJzZQAHAml0AAgCYWkACQJpZAAKAmlwAAsCZXMADAJlZQANA2VscwAOA2VsZQAPAnJpABACcmUAEQFmABICbXMAEwVwYXJzZQAUC19faGVhcF9iYXNlAwEKzkQwaAEBf0EAIAA2AoAKQQAoAtwJIgEgAEEBdGoiAEEAOwEAQQAgAEECaiIANgKECkEAIAA2AogKQQBBADYC4AlBAEEANgLwCUEAQQA2AugJQQBBADYC5AlBAEEANgL4CUEAQQA2AuwJIAEL0wEBA39BACgC8AkhBEEAQQAoAogKIgU2AvAJQQAgBDYC9AlBACAFQSRqNgKICiAEQSBqQeAJIAQbIAU2AgBBACgC1AkhBEEAKALQCSEGIAUgATYCACAFIAA2AgggBSACIAJBAmpBACAGIANGIgAbIAQgA0YiBBs2AgwgBSADNgIUIAVBADYCECAFIAI2AgQgBUEANgIgIAVBA0EBQQIgABsgBBs2AhwgBUEAKALQCSADRiICOgAYAkACQCACDQBBACgC1AkgA0cNAQtBAEEBOgCMCgsLXgEBf0EAKAL4CSIEQRBqQeQJIAQbQQAoAogKIgQ2AgBBACAENgL4CUEAIARBFGo2AogKQQBBAToAjAogBEEANgIQIAQgAzYCDCAEIAI2AgggBCABNgIEIAQgADYCAAsIAEEAKAKQCgsVAEEAKALoCSgCAEEAKALcCWtBAXULHgEBf0EAKALoCSgCBCIAQQAoAtwJa0EBdUF/IAAbCxUAQQAoAugJKAIIQQAoAtwJa0EBdQseAQF/QQAoAugJKAIMIgBBACgC3AlrQQF1QX8gABsLCwBBACgC6AkoAhwLHgEBf0EAKALoCSgCECIAQQAoAtwJa0EBdUF/IAAbCzsBAX8CQEEAKALoCSgCFCIAQQAoAtAJRw0AQX8PCwJAIABBACgC1AlHDQBBfg8LIABBACgC3AlrQQF1CwsAQQAoAugJLQAYCxUAQQAoAuwJKAIAQQAoAtwJa0EBdQsVAEEAKALsCSgCBEEAKALcCWtBAXULHgEBf0EAKALsCSgCCCIAQQAoAtwJa0EBdUF/IAAbCx4BAX9BACgC7AkoAgwiAEEAKALcCWtBAXVBfyAAGwslAQF/QQBBACgC6AkiAEEgakHgCSAAGygCACIANgLoCSAAQQBHCyUBAX9BAEEAKALsCSIAQRBqQeQJIAAbKAIAIgA2AuwJIABBAEcLCABBAC0AlAoLCABBAC0AjAoL3Q0BBX8jAEGA0ABrIgAkAEEAQQE6AJQKQQBBACgC2Ak2ApwKQQBBACgC3AlBfmoiATYCsApBACABQQAoAoAKQQF0aiICNgK0CkEAQQA6AIwKQQBBADsBlgpBAEEAOwGYCkEAQQA6AKAKQQBBADYCkApBAEEAOgD8CUEAIABBgBBqNgKkCkEAIAA2AqgKQQBBADoArAoCQAJAAkACQANAQQAgAUECaiIDNgKwCiABIAJPDQECQCADLwEAIgJBd2pBBUkNAAJAAkACQAJAAkAgAkGbf2oOBQEICAgCAAsgAkEgRg0EIAJBL0YNAyACQTtGDQIMBwtBAC8BmAoNASADEBVFDQEgAUEEakGCCEEKEC8NARAWQQAtAJQKDQFBAEEAKAKwCiIBNgKcCgwHCyADEBVFDQAgAUEEakGMCEEKEC8NABAXC0EAQQAoArAKNgKcCgwBCwJAIAEvAQQiA0EqRg0AIANBL0cNBBAYDAELQQEQGQtBACgCtAohAkEAKAKwCiEBDAALC0EAIQIgAyEBQQAtAPwJDQIMAQtBACABNgKwCkEAQQA6AJQKCwNAQQAgAUECaiIDNgKwCgJAAkACQAJAAkACQAJAIAFBACgCtApPDQAgAy8BACICQXdqQQVJDQYCQAJAAkACQAJAAkACQAJAAkACQCACQWBqDgoQDwYPDw8PBQECAAsCQAJAAkACQCACQaB/ag4KCxISAxIBEhISAgALIAJBhX9qDgMFEQYJC0EALwGYCg0QIAMQFUUNECABQQRqQYIIQQoQLw0QEBYMEAsgAxAVRQ0PIAFBBGpBjAhBChAvDQ8QFwwPCyADEBVFDQ4gASkABELsgISDsI7AOVINDiABLwEMIgNBd2oiAUEXSw0MQQEgAXRBn4CABHFFDQwMDQtBAEEALwGYCiIBQQFqOwGYCkEAKAKkCiABQQN0aiIBQQE2AgAgAUEAKAKcCjYCBAwNC0EALwGYCiIDRQ0JQQAgA0F/aiIDOwGYCkEALwGWCiICRQ0MQQAoAqQKIANB//8DcUEDdGooAgBBBUcNDAJAIAJBAnRBACgCqApqQXxqKAIAIgMoAgQNACADQQAoApwKQQJqNgIEC0EAIAJBf2o7AZYKIAMgAUEEajYCDAwMCwJAQQAoApwKIgEvAQBBKUcNAEEAKALwCSIDRQ0AIAMoAgQgAUcNAEEAQQAoAvQJIgM2AvAJAkAgA0UNACADQQA2AiAMAQtBAEEANgLgCQtBAEEALwGYCiIDQQFqOwGYCkEAKAKkCiADQQN0aiIDQQZBAkEALQCsChs2AgAgAyABNgIEQQBBADoArAoMCwtBAC8BmAoiAUUNB0EAIAFBf2oiATsBmApBACgCpAogAUH//wNxQQN0aigCAEEERg0EDAoLQScQGgwJC0EiEBoMCAsgAkEvRw0HAkACQCABLwEEIgFBKkYNACABQS9HDQEQGAwKC0EBEBkMCQsCQAJAAkACQEEAKAKcCiIBLwEAIgMQG0UNAAJAAkAgA0FVag4EAAkBAwkLIAFBfmovAQBBK0YNAwwICyABQX5qLwEAQS1GDQIMBwsgA0EpRw0BQQAoAqQKQQAvAZgKIgJBA3RqKAIEEBxFDQIMBgsgAUF+ai8BAEFQakH//wNxQQpPDQULQQAvAZgKIQILAkACQCACQf//A3EiAkUNACADQeYARw0AQQAoAqQKIAJBf2pBA3RqIgQoAgBBAUcNACABQX5qLwEAQe8ARw0BIAQoAgRBlghBAxAdRQ0BDAULIANB/QBHDQBBACgCpAogAkEDdGoiAigCBBAeDQQgAigCAEEGRg0ECyABEB8NAyADRQ0DIANBL0ZBAC0AoApBAEdxDQMCQEEAKAL4CSICRQ0AIAEgAigCAEkNACABIAIoAgRNDQQLIAFBfmohAUEAKALcCSECAkADQCABQQJqIgQgAk0NAUEAIAE2ApwKIAEvAQAhAyABQX5qIgQhASADECBFDQALIARBAmohBAsCQCADQf//A3EQIUUNACAEQX5qIQECQANAIAFBAmoiAyACTQ0BQQAgATYCnAogAS8BACEDIAFBfmoiBCEBIAMQIQ0ACyAEQQJqIQMLIAMQIg0EC0EAQQE6AKAKDAcLQQAoAqQKQQAvAZgKIgFBA3QiA2pBACgCnAo2AgRBACABQQFqOwGYCkEAKAKkCiADakEDNgIACxAjDAULQQAtAPwJQQAvAZYKQQAvAZgKcnJFIQIMBwsQJEEAQQA6AKAKDAMLECVBACECDAULIANBoAFHDQELQQBBAToArAoLQQBBACgCsAo2ApwKC0EAKAKwCiEBDAALCyAAQYDQAGokACACCxoAAkBBACgC3AkgAEcNAEEBDwsgAEF+ahAmC/4KAQZ/QQBBACgCsAoiAEEMaiIBNgKwCkEAKAL4CSECQQEQKSEDAkACQAJAAkACQAJAAkACQAJAQQAoArAKIgQgAUcNACADEChFDQELAkACQAJAAkACQAJAAkAgA0EqRg0AIANB+wBHDQFBACAEQQJqNgKwCkEBECkhA0EAKAKwCiEEA0ACQAJAIANB//8DcSIDQSJGDQAgA0EnRg0AIAMQLBpBACgCsAohAwwBCyADEBpBAEEAKAKwCkECaiIDNgKwCgtBARApGgJAIAQgAxAtIgNBLEcNAEEAQQAoArAKQQJqNgKwCkEBECkhAwsgA0H9AEYNA0EAKAKwCiIFIARGDQ8gBSEEIAVBACgCtApNDQAMDwsLQQAgBEECajYCsApBARApGkEAKAKwCiIDIAMQLRoMAgtBAEEAOgCUCgJAAkACQAJAAkACQCADQZ9/ag4MAgsEAQsDCwsLCwsFAAsgA0H2AEYNBAwKC0EAIARBDmoiAzYCsAoCQAJAAkBBARApQZ9/ag4GABICEhIBEgtBACgCsAoiBSkAAkLzgOSD4I3AMVINESAFLwEKECFFDRFBACAFQQpqNgKwCkEAECkaC0EAKAKwCiIFQQJqQbIIQQ4QLw0QIAUvARAiAkF3aiIBQRdLDQ1BASABdEGfgIAEcUUNDQwOC0EAKAKwCiIFKQACQuyAhIOwjsA5Ug0PIAUvAQoiAkF3aiIBQRdNDQYMCgtBACAEQQpqNgKwCkEAECkaQQAoArAKIQQLQQAgBEEQajYCsAoCQEEBECkiBEEqRw0AQQBBACgCsApBAmo2ArAKQQEQKSEEC0EAKAKwCiEDIAQQLBogA0EAKAKwCiIEIAMgBBACQQBBACgCsApBfmo2ArAKDwsCQCAEKQACQuyAhIOwjsA5Ug0AIAQvAQoQIEUNAEEAIARBCmo2ArAKQQEQKSEEQQAoArAKIQMgBBAsGiADQQAoArAKIgQgAyAEEAJBAEEAKAKwCkF+ajYCsAoPC0EAIARBBGoiBDYCsAoLQQAgBEEGajYCsApBAEEAOgCUCkEBECkhBEEAKAKwCiEDIAQQLCEEQQAoArAKIQIgBEHf/wNxIgFB2wBHDQNBACACQQJqNgKwCkEBECkhBUEAKAKwCiEDQQAhBAwEC0EAQQE6AIwKQQBBACgCsApBAmo2ArAKC0EBECkhBEEAKAKwCiEDAkAgBEHmAEcNACADQQJqQawIQQYQLw0AQQAgA0EIajYCsAogAEEBEClBABArIAJBEGpB5AkgAhshAwNAIAMoAgAiA0UNBSADQgA3AgggA0EQaiEDDAALC0EAIANBfmo2ArAKDAMLQQEgAXRBn4CABHFFDQMMBAtBASEECwNAAkACQCAEDgIAAQELIAVB//8DcRAsGkEBIQQMAQsCQAJAQQAoArAKIgQgA0YNACADIAQgAyAEEAJBARApIQQCQCABQdsARw0AIARBIHJB/QBGDQQLQQAoArAKIQMCQCAEQSxHDQBBACADQQJqNgKwCkEBECkhBUEAKAKwCiEDIAVBIHJB+wBHDQILQQAgA0F+ajYCsAoLIAFB2wBHDQJBACACQX5qNgKwCg8LQQAhBAwACwsPCyACQaABRg0AIAJB+wBHDQQLQQAgBUEKajYCsApBARApIgVB+wBGDQMMAgsCQCACQVhqDgMBAwEACyACQaABRw0CC0EAIAVBEGo2ArAKAkBBARApIgVBKkcNAEEAQQAoArAKQQJqNgKwCkEBECkhBQsgBUEoRg0BC0EAKAKwCiEBIAUQLBpBACgCsAoiBSABTQ0AIAQgAyABIAUQAkEAQQAoArAKQX5qNgKwCg8LIAQgA0EAQQAQAkEAIARBDGo2ArAKDwsQJQuFDAEKf0EAQQAoArAKIgBBDGoiATYCsApBARApIQJBACgCsAohAwJAAkACQAJAAkACQAJAAkAgAkEuRw0AQQAgA0ECajYCsAoCQEEBECkiAkHkAEYNAAJAIAJB8wBGDQAgAkHtAEcNB0EAKAKwCiICQQJqQZwIQQYQLw0HAkBBACgCnAoiAxAqDQAgAy8BAEEuRg0ICyAAIAAgAkEIakEAKALUCRABDwtBACgCsAoiAkECakGiCEEKEC8NBgJAQQAoApwKIgMQKg0AIAMvAQBBLkYNBwtBACEEQQAgAkEMajYCsApBASEFQQUhBkEBECkhAkEAIQdBASEIDAILQQAoArAKIgIpAAJC5YCYg9CMgDlSDQUCQEEAKAKcCiIDECoNACADLwEAQS5GDQYLQQAhBEEAIAJBCmo2ArAKQQIhCEEHIQZBASEHQQEQKSECQQEhBQwBCwJAAkACQAJAIAJB8wBHDQAgAyABTQ0AIANBAmpBoghBChAvDQACQCADLwEMIgRBd2oiB0EXSw0AQQEgB3RBn4CABHENAgsgBEGgAUYNAQtBACEHQQchBkEBIQQgAkHkAEYNAQwCC0EAIQRBACADQQxqIgI2ArAKQQEhBUEBECkhCQJAQQAoArAKIgYgAkYNAEHmACECAkAgCUHmAEYNAEEFIQZBACEHQQEhCCAJIQIMBAtBACEHQQEhCCAGQQJqQawIQQYQLw0EIAYvAQgQIEUNBAtBACEHQQAgAzYCsApBByEGQQEhBEEAIQVBACEIIAkhAgwCCyADIABBCmpNDQBBACEIQeQAIQICQCADKQACQuWAmIPQjIA5Ug0AAkACQCADLwEKIgRBd2oiB0EXSw0AQQEgB3RBn4CABHENAQtBACEIIARBoAFHDQELQQAhBUEAIANBCmo2ArAKQSohAkEBIQdBAiEIQQEQKSIJQSpGDQRBACADNgKwCkEBIQRBACEHQQAhCCAJIQIMAgsgAyEGQQAhBwwCC0EAIQVBACEICwJAIAJBKEcNAEEAKAKkCkEALwGYCiICQQN0aiIDQQAoArAKNgIEQQAgAkEBajsBmAogA0EFNgIAQQAoApwKLwEAQS5GDQRBAEEAKAKwCiIDQQJqNgKwCkEBECkhAiAAQQAoArAKQQAgAxABAkACQCAFDQBBACgC8AkhAQwBC0EAKALwCSIBIAY2AhwLQQBBAC8BlgoiA0EBajsBlgpBACgCqAogA0ECdGogATYCAAJAIAJBIkYNACACQSdGDQBBAEEAKAKwCkF+ajYCsAoPCyACEBpBAEEAKAKwCkECaiICNgKwCgJAAkACQEEBEClBV2oOBAECAgACC0EAQQAoArAKQQJqNgKwCkEBECkaQQAoAvAJIgMgAjYCBCADQQE6ABggA0EAKAKwCiICNgIQQQAgAkF+ajYCsAoPC0EAKALwCSIDIAI2AgQgA0EBOgAYQQBBAC8BmApBf2o7AZgKIANBACgCsApBAmo2AgxBAEEALwGWCkF/ajsBlgoPC0EAQQAoArAKQX5qNgKwCg8LAkAgBEEBcyACQfsAR3INAEEAKAKwCiECQQAvAZgKDQUDQAJAAkACQCACQQAoArQKTw0AQQEQKSICQSJGDQEgAkEnRg0BIAJB/QBHDQJBAEEAKAKwCkECajYCsAoLQQEQKSEDQQAoArAKIQICQCADQeYARw0AIAJBAmpBrAhBBhAvDQcLQQAgAkEIajYCsAoCQEEBECkiAkEiRg0AIAJBJ0cNBwsgACACQQAQKw8LIAIQGgtBAEEAKAKwCkECaiICNgKwCgwACwsCQAJAIAJBWWoOBAMBAQMACyACQSJGDQILQQAoArAKIQYLIAYgAUcNAEEAIABBCmo2ArAKDwsgAkEqRyAHcQ0DQQAvAZgKQf//A3ENA0EAKAKwCiECQQAoArQKIQEDQCACIAFPDQECQAJAIAIvAQAiA0EnRg0AIANBIkcNAQsgACADIAgQKw8LQQAgAkECaiICNgKwCgwACwsQJQsPC0EAIAJBfmo2ArAKDwtBAEEAKAKwCkF+ajYCsAoLRwEDf0EAKAKwCkECaiEAQQAoArQKIQECQANAIAAiAkF+aiABTw0BIAJBAmohACACLwEAQXZqDgQBAAABAAsLQQAgAjYCsAoLmAEBA39BAEEAKAKwCiIBQQJqNgKwCiABQQZqIQFBACgCtAohAgNAAkACQAJAIAFBfGogAk8NACABQX5qLwEAIQMCQAJAIAANACADQSpGDQEgA0F2ag4EAgQEAgQLIANBKkcNAwsgAS8BAEEvRw0CQQAgAUF+ajYCsAoMAQsgAUF+aiEBC0EAIAE2ArAKDwsgAUECaiEBDAALC4gBAQR/QQAoArAKIQFBACgCtAohAgJAAkADQCABIgNBAmohASADIAJPDQEgAS8BACIEIABGDQICQCAEQdwARg0AIARBdmoOBAIBAQIBCyADQQRqIQEgAy8BBEENRw0AIANBBmogASADLwEGQQpGGyEBDAALC0EAIAE2ArAKECUPC0EAIAE2ArAKC2wBAX8CQAJAIABBX2oiAUEFSw0AQQEgAXRBMXENAQsgAEFGakH//wNxQQZJDQAgAEEpRyAAQVhqQf//A3FBB0lxDQACQCAAQaV/ag4EAQAAAQALIABB/QBHIABBhX9qQf//A3FBBElxDwtBAQsuAQF/QQEhAQJAIABBpglBBRAdDQAgAEGWCEEDEB0NACAAQbAJQQIQHSEBCyABC0YBA39BACEDAkAgACACQQF0IgJrIgRBAmoiAEEAKALcCSIFSQ0AIAAgASACEC8NAAJAIAAgBUcNAEEBDwsgBBAmIQMLIAMLgwEBAn9BASEBAkACQAJAAkACQAJAIAAvAQAiAkFFag4EBQQEAQALAkAgAkGbf2oOBAMEBAIACyACQSlGDQQgAkH5AEcNAyAAQX5qQbwJQQYQHQ8LIABBfmovAQBBPUYPCyAAQX5qQbQJQQQQHQ8LIABBfmpByAlBAxAdDwtBACEBCyABC7QDAQJ/QQAhAQJAAkACQAJAAkACQAJAAkACQAJAIAAvAQBBnH9qDhQAAQIJCQkJAwkJBAUJCQYJBwkJCAkLAkACQCAAQX5qLwEAQZd/ag4EAAoKAQoLIABBfGpByghBAhAdDwsgAEF8akHOCEEDEB0PCwJAAkACQCAAQX5qLwEAQY1/ag4DAAECCgsCQCAAQXxqLwEAIgJB4QBGDQAgAkHsAEcNCiAAQXpqQeUAECcPCyAAQXpqQeMAECcPCyAAQXxqQdQIQQQQHQ8LIABBfGpB3AhBBhAdDwsgAEF+ai8BAEHvAEcNBiAAQXxqLwEAQeUARw0GAkAgAEF6ai8BACICQfAARg0AIAJB4wBHDQcgAEF4akHoCEEGEB0PCyAAQXhqQfQIQQIQHQ8LIABBfmpB+AhBBBAdDwtBASEBIABBfmoiAEHpABAnDQQgAEGACUEFEB0PCyAAQX5qQeQAECcPCyAAQX5qQYoJQQcQHQ8LIABBfmpBmAlBBBAdDwsCQCAAQX5qLwEAIgJB7wBGDQAgAkHlAEcNASAAQXxqQe4AECcPCyAAQXxqQaAJQQMQHSEBCyABCzQBAX9BASEBAkAgAEF3akH//wNxQQVJDQAgAEGAAXJBoAFGDQAgAEEuRyAAEChxIQELIAELMAEBfwJAAkAgAEF3aiIBQRdLDQBBASABdEGNgIAEcQ0BCyAAQaABRg0AQQAPC0EBC04BAn9BACEBAkACQCAALwEAIgJB5QBGDQAgAkHrAEcNASAAQX5qQfgIQQQQHQ8LIABBfmovAQBB9QBHDQAgAEF8akHcCEEGEB0hAQsgAQveAQEEf0EAKAKwCiEAQQAoArQKIQECQAJAAkADQCAAIgJBAmohACACIAFPDQECQAJAAkAgAC8BACIDQaR/ag4FAgMDAwEACyADQSRHDQIgAi8BBEH7AEcNAkEAIAJBBGoiADYCsApBAEEALwGYCiICQQFqOwGYCkEAKAKkCiACQQN0aiICQQQ2AgAgAiAANgIEDwtBACAANgKwCkEAQQAvAZgKQX9qIgA7AZgKQQAoAqQKIABB//8DcUEDdGooAgBBA0cNAwwECyACQQRqIQAMAAsLQQAgADYCsAoLECULC3ABAn8CQAJAA0BBAEEAKAKwCiIAQQJqIgE2ArAKIABBACgCtApPDQECQAJAAkAgAS8BACIBQaV/ag4CAQIACwJAIAFBdmoOBAQDAwQACyABQS9HDQIMBAsQLhoMAQtBACAAQQRqNgKwCgwACwsQJQsLNQEBf0EAQQE6APwJQQAoArAKIQBBAEEAKAK0CkECajYCsApBACAAQQAoAtwJa0EBdTYCkAoLQwECf0EBIQECQCAALwEAIgJBd2pB//8DcUEFSQ0AIAJBgAFyQaABRg0AQQAhASACEChFDQAgAkEuRyAAECpyDwsgAQs9AQJ/QQAhAgJAQQAoAtwJIgMgAEsNACAALwEAIAFHDQACQCADIABHDQBBAQ8LIABBfmovAQAQICECCyACC2gBAn9BASEBAkACQCAAQV9qIgJBBUsNAEEBIAJ0QTFxDQELIABB+P8DcUEoRg0AIABBRmpB//8DcUEGSQ0AAkAgAEGlf2oiAkEDSw0AIAJBAUcNAQsgAEGFf2pB//8DcUEESSEBCyABC5wBAQN/QQAoArAKIQECQANAAkACQCABLwEAIgJBL0cNAAJAIAEvAQIiAUEqRg0AIAFBL0cNBBAYDAILIAAQGQwBCwJAAkAgAEUNACACQXdqIgFBF0sNAUEBIAF0QZ+AgARxRQ0BDAILIAIQIUUNAwwBCyACQaABRw0CC0EAQQAoArAKIgNBAmoiATYCsAogA0EAKAK0CkkNAAsLIAILMQEBf0EAIQECQCAALwEAQS5HDQAgAEF+ai8BAEEuRw0AIABBfGovAQBBLkYhAQsgAQumBAEBfwJAIAFBIkYNACABQSdGDQAQJQ8LQQAoArAKIQMgARAaIAAgA0ECakEAKAKwCkEAKALQCRABAkAgAkEBSA0AQQAoAvAJQQRBBiACQQFGGzYCHAtBAEEAKAKwCkECajYCsAoCQAJAAkACQEEAECkiAUHhAEYNACABQfcARg0BQQAoArAKIQEMAgtBACgCsAoiAUECakHACEEKEC8NAUEGIQIMAgtBACgCsAoiAS8BAkHpAEcNACABLwEEQfQARw0AQQQhAiABLwEGQegARg0BC0EAIAFBfmo2ArAKDwtBACABIAJBAXRqNgKwCgJAQQEQKUH7AEYNAEEAIAE2ArAKDwtBACgCsAoiACECA0BBACACQQJqNgKwCgJAAkACQEEBECkiAkEiRg0AIAJBJ0cNAUEnEBpBAEEAKAKwCkECajYCsApBARApIQIMAgtBIhAaQQBBACgCsApBAmo2ArAKQQEQKSECDAELIAIQLCECCwJAIAJBOkYNAEEAIAE2ArAKDwtBAEEAKAKwCkECajYCsAoCQEEBECkiAkEiRg0AIAJBJ0YNAEEAIAE2ArAKDwsgAhAaQQBBACgCsApBAmo2ArAKAkACQEEBECkiAkEsRg0AIAJB/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
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
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
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
}
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
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
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
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
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
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
|
-
|
|
900
|
+
onError(error);
|
|
677
901
|
}
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
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
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
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
|
-
|
|
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 =
|
|
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 =
|
|
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:
|
|
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,
|
|
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
|
|
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
|
-
},
|
|
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
|
-
(
|
|
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
|
-
|
|
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
|
-
})
|
|
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
|
|
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
|
|
1344
|
+
let imported = await configJiti.import(configPath, {
|
|
923
1345
|
default: !0
|
|
924
|
-
});
|
|
925
|
-
if (
|
|
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
|
|
933
|
-
|
|
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
|
-
|
|
939
|
-
|
|
940
|
-
|
|
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 =
|
|
958
|
-
let routesPath = findEntryFile(
|
|
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
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
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
|
-
|
|
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:
|
|
1012
|
-
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,
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
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
|
-
},
|
|
1032
|
-
|
|
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
|
-
])),
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
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
|
-
|
|
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
|
-
}, {}),
|
|
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
|
-
})
|
|
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('&', '&').replaceAll('<', '<').replaceAll('>', '>')
|
|
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?.
|
|
1066
|
-
let serverBuildDir =
|
|
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 =
|
|
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
|
-
})
|
|
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
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
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
|
|
1331
|
-
|
|
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
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
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
|
-
|
|
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':
|
|
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
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
2296
|
+
node: {
|
|
2297
|
+
source: {
|
|
2298
|
+
entry: nodeEntries
|
|
2299
|
+
},
|
|
2300
|
+
output: {
|
|
2301
|
+
distPath: {
|
|
2302
|
+
root: external_pathe_resolve(buildDirectory, 'server')
|
|
1407
2303
|
},
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
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
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
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
|
|
1451
|
-
let output = rspackConfig.output
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
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
|
|
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
|
-
|
|
1692
|
-
let
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
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
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
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
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
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
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
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
|
-
|
|
1775
|
-
|
|
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
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
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
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
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 };
|