rsbuild-plugin-react-router 0.4.0 → 0.5.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 +17 -35
- package/dist/{451.js → 511.js} +92 -1
- package/dist/build-output-transforms.d.ts +4 -3
- package/dist/dev-background-resources.d.ts +1 -3
- package/dist/federation.d.ts +2 -0
- package/dist/index.cjs +153 -335
- package/dist/index.js +129 -407
- package/dist/performance.d.ts +4 -1
- package/dist/route-module-transform-loader.d.ts +14 -0
- package/dist/route-module-transform-loader.js +44 -0
- package/dist/route-module-transform-rules.d.ts +14 -0
- package/dist/route-transform-tasks.d.ts +1 -0
- package/dist/types.d.ts +4 -5
- package/package.json +13 -14
- package/src/build-output-transforms.ts +28 -24
- package/src/dev-background-resources.ts +1 -16
- package/src/federation.ts +38 -0
- package/src/index.ts +38 -57
- package/src/performance.ts +11 -2
- package/src/route-module-transform-loader.ts +149 -0
- package/src/route-module-transform-rules.ts +115 -0
- package/src/route-transform-tasks.ts +5 -4
- package/src/types.ts +4 -5
- package/dist/parallel-route-transform-protocol.d.ts +0 -25
- package/dist/parallel-route-transform-worker.d.ts +0 -1
- package/dist/parallel-route-transform-worker.js +0 -38
- package/dist/parallel-route-transforms.d.ts +0 -29
- package/src/parallel-route-transform-protocol.ts +0 -35
- package/src/parallel-route-transform-worker.ts +0 -82
- package/src/parallel-route-transforms.ts +0 -458
package/dist/performance.d.ts
CHANGED
|
@@ -12,12 +12,15 @@ export declare const roundMs: (value: number) => number;
|
|
|
12
12
|
export type ReactRouterPerformanceReport = {
|
|
13
13
|
environment: string;
|
|
14
14
|
compilerLifecycleMs?: number;
|
|
15
|
+
partial?: boolean;
|
|
16
|
+
workerId?: string;
|
|
15
17
|
operations: Record<string, OperationTiming>;
|
|
16
18
|
};
|
|
19
|
+
export declare const formatReactRouterPerformanceReport: (report: ReactRouterPerformanceReport) => string;
|
|
17
20
|
export type ReactRouterPerformanceProfiler = {
|
|
18
21
|
record<T>(environment: string | undefined, operation: string, resource: string, callback: () => Promise<T>): Promise<T>;
|
|
19
22
|
recordSync<T>(environment: string | undefined, operation: string, resource: string, callback: () => T): T;
|
|
20
|
-
flush(environment: string | undefined, details?: Pick<ReactRouterPerformanceReport, 'compilerLifecycleMs'>): void;
|
|
23
|
+
flush(environment: string | undefined, details?: Pick<ReactRouterPerformanceReport, 'compilerLifecycleMs' | 'partial' | 'workerId'>): void;
|
|
21
24
|
};
|
|
22
25
|
export declare const createReactRouterPerformanceProfiler: ({ enabled, log, }: {
|
|
23
26
|
enabled: boolean;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { LoaderDefinition } from '@rspack/core';
|
|
2
|
+
export type RouteModuleTransformLoaderOptions = {
|
|
3
|
+
environmentName: string;
|
|
4
|
+
performanceScopeId: string;
|
|
5
|
+
logPerformance: boolean;
|
|
6
|
+
ssr: boolean;
|
|
7
|
+
isBuild: boolean;
|
|
8
|
+
isSpaMode: boolean;
|
|
9
|
+
rootRoutePath: string | null;
|
|
10
|
+
devHmr: boolean;
|
|
11
|
+
};
|
|
12
|
+
export declare const flushRouteModuleTransformLoaderPerformance: () => void;
|
|
13
|
+
declare const routeModuleTransformLoader: LoaderDefinition<RouteModuleTransformLoaderOptions>;
|
|
14
|
+
export default routeModuleTransformLoader;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
let performanceFlushTimer;
|
|
2
|
+
import { threadId } from "node:worker_threads";
|
|
3
|
+
import remapping from "@jridgewell/remapping";
|
|
4
|
+
import { createReactRouterPerformanceProfiler, executeRouteTransformTask } from "./511.js";
|
|
5
|
+
let performanceWorkerId = `process-${process.pid}:thread-${threadId}`, performanceProfilersByScope = new Map(), flushRouteModuleTransformLoaderPerformance = ()=>{
|
|
6
|
+
for (let profilers of (performanceFlushTimer && (clearTimeout(performanceFlushTimer), performanceFlushTimer = void 0), performanceProfilersByScope.values()))for (let [environment, profiler] of profilers)profiler.flush('unknown' === environment ? void 0 : environment, {
|
|
7
|
+
partial: !0,
|
|
8
|
+
workerId: performanceWorkerId
|
|
9
|
+
});
|
|
10
|
+
performanceProfilersByScope.clear();
|
|
11
|
+
};
|
|
12
|
+
process.once('beforeExit', flushRouteModuleTransformLoaderPerformance);
|
|
13
|
+
let route_module_transform_loader_routeModuleTransformLoader = async function(source, inputSourceMap) {
|
|
14
|
+
let callback = this.async(), options = this.getOptions(), transform = ()=>executeRouteTransformTask({
|
|
15
|
+
kind: 'routeModule',
|
|
16
|
+
code: String(source),
|
|
17
|
+
resource: this.resource,
|
|
18
|
+
resourcePath: this.resourcePath,
|
|
19
|
+
environmentName: options.environmentName,
|
|
20
|
+
sourceMaps: !!this.sourceMap,
|
|
21
|
+
ssr: options.ssr,
|
|
22
|
+
isBuild: options.isBuild,
|
|
23
|
+
isSpaMode: options.isSpaMode,
|
|
24
|
+
rootRoutePath: options.rootRoutePath,
|
|
25
|
+
devHmr: options.devHmr
|
|
26
|
+
});
|
|
27
|
+
try {
|
|
28
|
+
var scopeId, environment;
|
|
29
|
+
let profilers, environmentKey, profiler, generatedMap, result = options.logPerformance ? await (scopeId = options.performanceScopeId, environment = options.environmentName, !(profilers = performanceProfilersByScope.get(scopeId)) && (profilers = new Map(), performanceProfilersByScope.set(scopeId, profilers)), environmentKey = environment ?? 'unknown', !(profiler = profilers.get(environmentKey)) && (profiler = createReactRouterPerformanceProfiler({
|
|
30
|
+
enabled: !0,
|
|
31
|
+
log: (message)=>console.info(message)
|
|
32
|
+
}), profilers.set(environmentKey, profiler)), profiler).record(options.environmentName, 'route:module', this.resource, transform) : await transform(), outputSourceMap = result.map && inputSourceMap ? (generatedMap = result.map, JSON.parse(remapping([
|
|
33
|
+
generatedMap,
|
|
34
|
+
inputSourceMap
|
|
35
|
+
], ()=>null).toString())) : result.map;
|
|
36
|
+
callback(null, result.code, outputSourceMap ?? void 0);
|
|
37
|
+
} catch (error) {
|
|
38
|
+
callback(error instanceof Error ? error : Error(String(error)));
|
|
39
|
+
} finally{
|
|
40
|
+
options.logPerformance && (performanceFlushTimer && clearTimeout(performanceFlushTimer), performanceFlushTimer = setTimeout(flushRouteModuleTransformLoaderPerformance, 50));
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
export default route_module_transform_loader_routeModuleTransformLoader;
|
|
44
|
+
export { flushRouteModuleTransformLoaderPerformance };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Rspack } from '@rsbuild/core';
|
|
2
|
+
import type { PluginOptions, Route } from './types.js';
|
|
3
|
+
export declare const shouldUseRouteModuleTransformLoader: (parallelRouteTransform: PluginOptions["parallelRouteTransform"]) => boolean;
|
|
4
|
+
export declare const registerRouteModuleTransformRules: (rspackConfig: Rspack.Configuration, { environmentName, ssr, isBuild, isSpaMode, rootRoutePath, devHmr, logPerformance, routeByFilePath, parallelRouteTransform, }: {
|
|
5
|
+
environmentName: string;
|
|
6
|
+
ssr: boolean;
|
|
7
|
+
isBuild: boolean;
|
|
8
|
+
isSpaMode: boolean;
|
|
9
|
+
rootRoutePath: string | null;
|
|
10
|
+
devHmr: boolean;
|
|
11
|
+
logPerformance: boolean;
|
|
12
|
+
routeByFilePath: Map<string, Route>;
|
|
13
|
+
parallelRouteTransform: PluginOptions["parallelRouteTransform"];
|
|
14
|
+
}) => void;
|
|
@@ -46,5 +46,6 @@ export type RouteTransformTask = RouteClientEntryTransformTask | RouteChunkTrans
|
|
|
46
46
|
export type RouteTransformTaskOptions = {
|
|
47
47
|
routeChunkCache?: RouteChunkCache;
|
|
48
48
|
};
|
|
49
|
+
export type RouteTransformRunner = (task: RouteTransformTask) => Promise<RouteTransformResult>;
|
|
49
50
|
export declare const executeRouteTransformTask: (task: RouteTransformTask, options?: RouteTransformTaskOptions) => Promise<RouteTransformResult>;
|
|
50
51
|
export {};
|
package/dist/types.d.ts
CHANGED
|
@@ -49,11 +49,10 @@ export type PluginOptions = {
|
|
|
49
49
|
*/
|
|
50
50
|
logPerformance?: boolean;
|
|
51
51
|
/**
|
|
52
|
-
* Run route transforms
|
|
53
|
-
* Pass `true` to
|
|
54
|
-
* the worker count, or `false` to disable.
|
|
55
|
-
* @default
|
|
56
|
-
* pool uses available CPU cores minus 2.
|
|
52
|
+
* Run route module transforms with Rspack's parallel loader workers.
|
|
53
|
+
* Pass `true` to use Rspack's default worker count, a positive integer to set
|
|
54
|
+
* the maximum worker count, or `false` to disable.
|
|
55
|
+
* @default false
|
|
57
56
|
*/
|
|
58
57
|
parallelRouteTransform?: boolean | number;
|
|
59
58
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rsbuild-plugin-react-router",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "React Router plugin for Rsbuild",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -49,6 +49,7 @@
|
|
|
49
49
|
"ignoreMissingDts": true
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
|
+
"@jridgewell/remapping": "^2.3.5",
|
|
52
53
|
"@react-router/node": "^7.13.0",
|
|
53
54
|
"@remix-run/node-fetch-server": "^0.13.0",
|
|
54
55
|
"@rspack/plugin-react-refresh": "^2.0.2",
|
|
@@ -65,13 +66,15 @@
|
|
|
65
66
|
},
|
|
66
67
|
"devDependencies": {
|
|
67
68
|
"@changesets/cli": "^2.29.8",
|
|
69
|
+
"@codspeed/vitest-plugin": "^5.7.1",
|
|
70
|
+
"@jridgewell/trace-mapping": "^0.3.31",
|
|
68
71
|
"@react-router/dev": "^8.0.1",
|
|
69
|
-
"@rsbuild/core": "2.1.
|
|
72
|
+
"@rsbuild/core": "2.1.5",
|
|
70
73
|
"@rsbuild/plugin-react": "2.1.0",
|
|
71
|
-
"@rslib/core": "^0.
|
|
72
|
-
"@rspack/core": "2.1.
|
|
73
|
-
"@rstest/core": "^0.
|
|
74
|
-
"@rstest/coverage-istanbul": "^0.
|
|
74
|
+
"@rslib/core": "^0.23.2",
|
|
75
|
+
"@rspack/core": "2.1.3",
|
|
76
|
+
"@rstest/core": "^0.11.0",
|
|
77
|
+
"@rstest/coverage-istanbul": "^0.11.0",
|
|
75
78
|
"@swc/helpers": "^0.5.23",
|
|
76
79
|
"@types/fs-extra": "11.0.4",
|
|
77
80
|
"@types/jsesc": "^3.0.3",
|
|
@@ -89,6 +92,7 @@
|
|
|
89
92
|
"react-router": "^7.13.0",
|
|
90
93
|
"react-router-dom": "^7.13.0",
|
|
91
94
|
"typescript": "^5.9.3",
|
|
95
|
+
"vitest": "^4.1.10",
|
|
92
96
|
"@rsbuild/config": "1.0.1"
|
|
93
97
|
},
|
|
94
98
|
"peerDependencies": {
|
|
@@ -107,14 +111,9 @@
|
|
|
107
111
|
},
|
|
108
112
|
"scripts": {
|
|
109
113
|
"build": "rslib build",
|
|
110
|
-
"bench": "node
|
|
111
|
-
"bench:
|
|
112
|
-
"bench:
|
|
113
|
-
"bench:smoke": "node scripts/bench-builds.mts --profile smoke --iterations 1 --warmup 0 --format both --out .benchmark/results/smoke",
|
|
114
|
-
"bench:baseline": "node scripts/bench-builds.mts --profile default --iterations 5 --warmup 1 --clean build --format both --out .benchmark/results/baseline",
|
|
115
|
-
"bench:full": "node scripts/bench-builds.mts --profile full --iterations 5 --warmup 1 --clean build --format both --out .benchmark/results/full",
|
|
116
|
-
"bench:large": "node scripts/bench-builds.mts --profile large --iterations 1 --warmup 0 --clean cold --format both --out .benchmark/results/large",
|
|
117
|
-
"bench:synthetic-app": "node scripts/bench-synthetic-app.mjs",
|
|
114
|
+
"bench": "pnpm build && node benchmarks/run.mts",
|
|
115
|
+
"bench:smoke": "pnpm build && node benchmarks/run.mts --iterations 1 --warmup 0",
|
|
116
|
+
"bench:codspeed": "pnpm build && vitest bench --run --config vitest.benchmark.config.mts",
|
|
118
117
|
"e2e": "pnpm build && pnpm test:package-interop && pnpm --filter './examples/{default-template,spa-mode,prerender,custom-node-server,cloudflare,client-only}' test:e2e",
|
|
119
118
|
"dev": "rslib build --watch",
|
|
120
119
|
"test": "rstest run",
|
|
@@ -6,10 +6,10 @@ import {
|
|
|
6
6
|
getReactRouterManifestForDev,
|
|
7
7
|
type ReactRouterManifestStats,
|
|
8
8
|
} from './manifest.js';
|
|
9
|
-
import type { RouteTransformExecutor } from './parallel-route-transforms.js';
|
|
10
9
|
import type { ReactRouterPerformanceProfiler } from './performance.js';
|
|
11
10
|
import { createBundlerRouteExportResolver } from './route-export-resolution.js';
|
|
12
11
|
import type { RouteChunkConfig } from './route-chunks.js';
|
|
12
|
+
import type { RouteTransformRunner } from './route-transform-tasks.js';
|
|
13
13
|
import type { PluginOptions, Route } from './types.js';
|
|
14
14
|
import { isSourceMapEnabled } from './warnings/warn-on-client-source-maps.js';
|
|
15
15
|
|
|
@@ -31,11 +31,12 @@ type RegisterBuildOutputTransformsOptions = {
|
|
|
31
31
|
appDirectory: string;
|
|
32
32
|
getAssetPrefix: () => string;
|
|
33
33
|
routeChunkOptions: Parameters<typeof getReactRouterManifestForDev>[5];
|
|
34
|
-
|
|
34
|
+
routeTransformRunner: RouteTransformRunner;
|
|
35
35
|
routeByFilePath: Map<string, Route>;
|
|
36
36
|
routeChunkConfig: RouteChunkConfig;
|
|
37
37
|
isBuild: boolean;
|
|
38
38
|
splitRouteModules: boolean;
|
|
39
|
+
useRouteModuleTransformApi: boolean;
|
|
39
40
|
ssr: boolean;
|
|
40
41
|
isSpaMode: boolean;
|
|
41
42
|
rootRoutePath: string;
|
|
@@ -54,11 +55,12 @@ export const registerBuildOutputTransforms = ({
|
|
|
54
55
|
appDirectory,
|
|
55
56
|
getAssetPrefix,
|
|
56
57
|
routeChunkOptions,
|
|
57
|
-
|
|
58
|
+
routeTransformRunner,
|
|
58
59
|
routeByFilePath,
|
|
59
60
|
routeChunkConfig,
|
|
60
61
|
isBuild,
|
|
61
62
|
splitRouteModules,
|
|
63
|
+
useRouteModuleTransformApi,
|
|
62
64
|
ssr,
|
|
63
65
|
isSpaMode,
|
|
64
66
|
rootRoutePath,
|
|
@@ -70,7 +72,7 @@ export const registerBuildOutputTransforms = ({
|
|
|
70
72
|
'route:module',
|
|
71
73
|
args.resource,
|
|
72
74
|
async () =>
|
|
73
|
-
|
|
75
|
+
routeTransformRunner({
|
|
74
76
|
kind: 'routeModule',
|
|
75
77
|
code: args.code,
|
|
76
78
|
resource: args.resource,
|
|
@@ -154,7 +156,7 @@ export const registerBuildOutputTransforms = ({
|
|
|
154
156
|
'route:client-entry',
|
|
155
157
|
args.resource,
|
|
156
158
|
async () =>
|
|
157
|
-
|
|
159
|
+
routeTransformRunner({
|
|
158
160
|
kind: 'routeClientEntry',
|
|
159
161
|
code: args.code,
|
|
160
162
|
resourcePath: args.resourcePath,
|
|
@@ -178,7 +180,7 @@ export const registerBuildOutputTransforms = ({
|
|
|
178
180
|
'route:chunk',
|
|
179
181
|
args.resource,
|
|
180
182
|
async () =>
|
|
181
|
-
|
|
183
|
+
routeTransformRunner({
|
|
182
184
|
kind: 'routeChunk',
|
|
183
185
|
code: args.code,
|
|
184
186
|
resource: args.resource,
|
|
@@ -204,7 +206,7 @@ export const registerBuildOutputTransforms = ({
|
|
|
204
206
|
'route:split-exports',
|
|
205
207
|
args.resource,
|
|
206
208
|
async () =>
|
|
207
|
-
|
|
209
|
+
routeTransformRunner({
|
|
208
210
|
kind: 'splitRouteExports',
|
|
209
211
|
code: args.code,
|
|
210
212
|
resourcePath: args.resourcePath,
|
|
@@ -244,7 +246,7 @@ export const registerBuildOutputTransforms = ({
|
|
|
244
246
|
'module:client-only-stub',
|
|
245
247
|
args.resource,
|
|
246
248
|
async () => {
|
|
247
|
-
return
|
|
249
|
+
return routeTransformRunner({
|
|
248
250
|
kind: 'clientOnlyStub',
|
|
249
251
|
code: args.code,
|
|
250
252
|
resourcePath: args.resourcePath,
|
|
@@ -257,22 +259,24 @@ export const registerBuildOutputTransforms = ({
|
|
|
257
259
|
)
|
|
258
260
|
);
|
|
259
261
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
262
|
+
if (useRouteModuleTransformApi) {
|
|
263
|
+
api.transform(
|
|
264
|
+
{
|
|
265
|
+
resourceQuery: /\?react-router-route/,
|
|
266
|
+
order: 'post',
|
|
267
|
+
},
|
|
268
|
+
transformRouteModule
|
|
269
|
+
);
|
|
267
270
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
271
|
+
api.transform(
|
|
272
|
+
{
|
|
273
|
+
test: path => routeByFilePath.has(path),
|
|
274
|
+
resourceQuery: {
|
|
275
|
+
not: /__react-router-build-client-route|react-router-route|route-chunk=/,
|
|
276
|
+
},
|
|
277
|
+
order: 'post',
|
|
273
278
|
},
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
);
|
|
279
|
+
transformRouteModule
|
|
280
|
+
);
|
|
281
|
+
}
|
|
278
282
|
};
|
|
@@ -18,7 +18,6 @@ import {
|
|
|
18
18
|
configRoutesToRouteManifestEntries,
|
|
19
19
|
type ReactRouterManifestForDev,
|
|
20
20
|
} from './manifest.js';
|
|
21
|
-
import type { RouteTransformExecutor } from './parallel-route-transforms.js';
|
|
22
21
|
import {
|
|
23
22
|
createRouteManifestSnapshot,
|
|
24
23
|
createRouteTopologyWatcher,
|
|
@@ -31,7 +30,6 @@ type RegisterReactRouterDevBackgroundResourcesOptions = {
|
|
|
31
30
|
api: RsbuildPluginAPI;
|
|
32
31
|
isBuild: boolean;
|
|
33
32
|
lazyCompilationPrewarm: PluginOptions['unstableLazyCompilationPrewarm'];
|
|
34
|
-
routeTransformExecutor: RouteTransformExecutor;
|
|
35
33
|
routeRestartMarkerPath: string;
|
|
36
34
|
watchDirectory: string;
|
|
37
35
|
getRouteTopology: () => Promise<Set<string>>;
|
|
@@ -135,7 +133,6 @@ export const registerReactRouterDevBackgroundResources = ({
|
|
|
135
133
|
api,
|
|
136
134
|
isBuild,
|
|
137
135
|
lazyCompilationPrewarm,
|
|
138
|
-
routeTransformExecutor,
|
|
139
136
|
routeRestartMarkerPath,
|
|
140
137
|
watchDirectory,
|
|
141
138
|
getRouteTopology,
|
|
@@ -213,10 +210,6 @@ export const registerReactRouterDevBackgroundResources = ({
|
|
|
213
210
|
scheduleRouteTopologyWatcher();
|
|
214
211
|
lazyCompilationPrewarmController?.schedule();
|
|
215
212
|
});
|
|
216
|
-
|
|
217
|
-
// Spawn transform workers now so thread startup overlaps Rsbuild's own
|
|
218
|
-
// compiler creation instead of delaying the first route transform.
|
|
219
|
-
routeTransformExecutor.prewarm();
|
|
220
213
|
}
|
|
221
214
|
|
|
222
215
|
const closeRouteTopologyWatcher = async (): Promise<void> => {
|
|
@@ -232,20 +225,12 @@ export const registerReactRouterDevBackgroundResources = ({
|
|
|
232
225
|
);
|
|
233
226
|
};
|
|
234
227
|
|
|
235
|
-
const closeRouteTransformExecutor = (): Promise<void> =>
|
|
236
|
-
routeTransformExecutor.close();
|
|
237
|
-
|
|
238
228
|
api.onCloseDevServer(() =>
|
|
239
229
|
closeAll(
|
|
240
230
|
'[rsbuild-plugin-react-router] Failed to close dev server resources.',
|
|
241
|
-
[
|
|
242
|
-
closeRouteTopologyWatcher,
|
|
243
|
-
closeLazyCompilationPrewarm,
|
|
244
|
-
closeRouteTransformExecutor,
|
|
245
|
-
]
|
|
231
|
+
[closeRouteTopologyWatcher, closeLazyCompilationPrewarm]
|
|
246
232
|
)
|
|
247
233
|
);
|
|
248
|
-
api.onCloseBuild(closeRouteTransformExecutor);
|
|
249
234
|
|
|
250
235
|
return {
|
|
251
236
|
setManifest(manifest) {
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { Rspack } from '@rsbuild/core';
|
|
2
|
+
|
|
3
|
+
type ModuleFederationPluginLike = {
|
|
4
|
+
name?: string;
|
|
5
|
+
_options?: { experiments?: { asyncStartup?: boolean } };
|
|
6
|
+
options?: { experiments?: { asyncStartup?: boolean } };
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export const ensureFederationAsyncStartup = (
|
|
10
|
+
rspackConfig: Rspack.Configuration | undefined
|
|
11
|
+
): void => {
|
|
12
|
+
if (!rspackConfig?.plugins?.length) {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
for (const plugin of rspackConfig.plugins) {
|
|
17
|
+
if (!plugin || typeof plugin !== 'object') {
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
20
|
+
const federationPlugin = plugin as ModuleFederationPluginLike;
|
|
21
|
+
if (
|
|
22
|
+
federationPlugin.name !== 'ModuleFederationPlugin' &&
|
|
23
|
+
federationPlugin.name !== 'RspackModuleFederationPlugin'
|
|
24
|
+
) {
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const pluginOptions = federationPlugin._options ?? federationPlugin.options;
|
|
29
|
+
if (!pluginOptions) {
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
pluginOptions.experiments = {
|
|
34
|
+
...pluginOptions.experiments,
|
|
35
|
+
asyncStartup: true,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
};
|
package/src/index.ts
CHANGED
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
PLUGIN_NAME,
|
|
19
19
|
} from './constants.js';
|
|
20
20
|
import { guardReactRouterLazyCompilation } from './lazy-compilation.js';
|
|
21
|
+
import { ensureFederationAsyncStartup } from './federation.js';
|
|
21
22
|
import { createReactRouterDevServerSetup } from './dev-server.js';
|
|
22
23
|
import {
|
|
23
24
|
generateWithProps,
|
|
@@ -52,9 +53,13 @@ import {
|
|
|
52
53
|
type RouteChunkConfig,
|
|
53
54
|
} from './route-chunks.js';
|
|
54
55
|
import {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
} from './
|
|
56
|
+
registerRouteModuleTransformRules,
|
|
57
|
+
shouldUseRouteModuleTransformLoader,
|
|
58
|
+
} from './route-module-transform-rules.js';
|
|
59
|
+
import {
|
|
60
|
+
executeRouteTransformTask,
|
|
61
|
+
type RouteTransformRunner,
|
|
62
|
+
} from './route-transform-tasks.js';
|
|
58
63
|
import { getRouteRestartMarkerPath, mergeWatchFiles } from './route-watch.js';
|
|
59
64
|
import { validateRouteConfig } from './route-config.js';
|
|
60
65
|
import {
|
|
@@ -106,42 +111,6 @@ export const shouldParallelizeEnvironmentBuilds = ({
|
|
|
106
111
|
}): boolean =>
|
|
107
112
|
!isBuild && spareCoreCount >= MIN_PARALLEL_ENVIRONMENT_BUILD_SPARE_CORES;
|
|
108
113
|
|
|
109
|
-
type ModuleFederationPluginLike = {
|
|
110
|
-
name?: string;
|
|
111
|
-
_options?: { experiments?: { asyncStartup?: boolean } };
|
|
112
|
-
options?: { experiments?: { asyncStartup?: boolean } };
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
const ensureFederationAsyncStartup = (
|
|
116
|
-
rspackConfig: Rspack.Configuration | undefined
|
|
117
|
-
): void => {
|
|
118
|
-
if (!rspackConfig?.plugins?.length) {
|
|
119
|
-
return;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
for (const plugin of rspackConfig.plugins) {
|
|
123
|
-
if (!plugin || typeof plugin !== 'object') {
|
|
124
|
-
continue;
|
|
125
|
-
}
|
|
126
|
-
const pluginName = (plugin as ModuleFederationPluginLike).name;
|
|
127
|
-
if (pluginName !== 'ModuleFederationPlugin') {
|
|
128
|
-
continue;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
const pluginOptions =
|
|
132
|
-
(plugin as ModuleFederationPluginLike)._options ??
|
|
133
|
-
(plugin as ModuleFederationPluginLike).options;
|
|
134
|
-
if (!pluginOptions) {
|
|
135
|
-
continue;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
pluginOptions.experiments = {
|
|
139
|
-
...pluginOptions.experiments,
|
|
140
|
-
asyncStartup: true,
|
|
141
|
-
};
|
|
142
|
-
}
|
|
143
|
-
};
|
|
144
|
-
|
|
145
114
|
const cssUrlAssetExtensions =
|
|
146
115
|
/\.(?:css|less|sass|scss|styl|stylus|pcss|postcss|sss)$/;
|
|
147
116
|
const urlAssetResourceQuery =
|
|
@@ -429,14 +398,11 @@ export const pluginReactRouter = (
|
|
|
429
398
|
rootRouteFile,
|
|
430
399
|
};
|
|
431
400
|
const routeChunkCache: RouteChunkCache = new Map();
|
|
432
|
-
const
|
|
433
|
-
parallelRouteTransform
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
routeChunkCache
|
|
437
|
-
splitRouteModules: Boolean(splitRouteModules),
|
|
438
|
-
isBuild,
|
|
439
|
-
});
|
|
401
|
+
const useRouteModuleTransformLoader = shouldUseRouteModuleTransformLoader(
|
|
402
|
+
pluginOptions.parallelRouteTransform
|
|
403
|
+
);
|
|
404
|
+
const routeTransformRunner: RouteTransformRunner = task =>
|
|
405
|
+
executeRouteTransformTask(task, { routeChunkCache });
|
|
440
406
|
const routeChunkOptions = {
|
|
441
407
|
splitRouteModules,
|
|
442
408
|
rootRouteFile,
|
|
@@ -457,7 +423,6 @@ export const pluginReactRouter = (
|
|
|
457
423
|
api,
|
|
458
424
|
isBuild,
|
|
459
425
|
lazyCompilationPrewarm: pluginOptions.unstableLazyCompilationPrewarm,
|
|
460
|
-
routeTransformExecutor,
|
|
461
426
|
routeRestartMarkerPath,
|
|
462
427
|
watchDirectory,
|
|
463
428
|
getRouteTopology: routeTopology.getRouteTopology,
|
|
@@ -783,7 +748,6 @@ export const pluginReactRouter = (
|
|
|
783
748
|
routeCount >= 256 &&
|
|
784
749
|
(config.performance?.printFileSize === undefined ||
|
|
785
750
|
config.performance.printFileSize === true);
|
|
786
|
-
|
|
787
751
|
return mergeRsbuildConfig(config, {
|
|
788
752
|
...(shouldCompactFileSizeReport
|
|
789
753
|
? {
|
|
@@ -800,7 +764,6 @@ export const pluginReactRouter = (
|
|
|
800
764
|
assetPrefix: config.output?.assetPrefix || '/',
|
|
801
765
|
},
|
|
802
766
|
dev: {
|
|
803
|
-
writeToDisk: true,
|
|
804
767
|
...lazyCompilation,
|
|
805
768
|
watchFiles: mergeWatchFiles(config.dev?.watchFiles, routeWatchFiles),
|
|
806
769
|
},
|
|
@@ -944,17 +907,34 @@ export const pluginReactRouter = (
|
|
|
944
907
|
return mergeEnvironmentConfig(config, {
|
|
945
908
|
tools: {
|
|
946
909
|
rspack: rspackConfig => {
|
|
910
|
+
const environmentDevHmrEnabled =
|
|
911
|
+
name === 'web' &&
|
|
912
|
+
!isBuild &&
|
|
913
|
+
devHmrRefreshRuntimePath !== undefined &&
|
|
914
|
+
config.mode === 'development' &&
|
|
915
|
+
config.dev?.hmr !== false &&
|
|
916
|
+
isRspackSwcReactRefreshEnabled(rspackConfig);
|
|
917
|
+
|
|
918
|
+
if (useRouteModuleTransformLoader) {
|
|
919
|
+
registerRouteModuleTransformRules(rspackConfig, {
|
|
920
|
+
environmentName: name,
|
|
921
|
+
ssr,
|
|
922
|
+
isBuild,
|
|
923
|
+
isSpaMode,
|
|
924
|
+
rootRoutePath,
|
|
925
|
+
devHmr: environmentDevHmrEnabled,
|
|
926
|
+
logPerformance,
|
|
927
|
+
routeByFilePath,
|
|
928
|
+
parallelRouteTransform: pluginOptions.parallelRouteTransform,
|
|
929
|
+
});
|
|
930
|
+
}
|
|
931
|
+
|
|
947
932
|
if (pluginOptions.federation) {
|
|
948
933
|
ensureFederationAsyncStartup(rspackConfig);
|
|
949
934
|
}
|
|
950
935
|
|
|
951
936
|
if (name === 'web') {
|
|
952
|
-
devHmrEnabled =
|
|
953
|
-
!isBuild &&
|
|
954
|
-
devHmrRefreshRuntimePath !== undefined &&
|
|
955
|
-
config.mode === 'development' &&
|
|
956
|
-
config.dev?.hmr !== false &&
|
|
957
|
-
isRspackSwcReactRefreshEnabled(rspackConfig);
|
|
937
|
+
devHmrEnabled = environmentDevHmrEnabled;
|
|
958
938
|
if (devHmrEnabled) {
|
|
959
939
|
devHdrSignal?.ensure();
|
|
960
940
|
}
|
|
@@ -1024,11 +1004,12 @@ export const pluginReactRouter = (
|
|
|
1024
1004
|
appDirectory,
|
|
1025
1005
|
getAssetPrefix: () => assetPrefix,
|
|
1026
1006
|
routeChunkOptions,
|
|
1027
|
-
|
|
1007
|
+
routeTransformRunner,
|
|
1028
1008
|
routeByFilePath,
|
|
1029
1009
|
routeChunkConfig,
|
|
1030
1010
|
isBuild,
|
|
1031
1011
|
splitRouteModules: Boolean(splitRouteModules),
|
|
1012
|
+
useRouteModuleTransformApi: !useRouteModuleTransformLoader,
|
|
1032
1013
|
ssr,
|
|
1033
1014
|
isSpaMode,
|
|
1034
1015
|
rootRoutePath,
|
package/src/performance.ts
CHANGED
|
@@ -54,9 +54,15 @@ export const roundMs = (value: number): number => Math.round(value * 10) / 10;
|
|
|
54
54
|
export type ReactRouterPerformanceReport = {
|
|
55
55
|
environment: string;
|
|
56
56
|
compilerLifecycleMs?: number;
|
|
57
|
+
partial?: boolean;
|
|
58
|
+
workerId?: string;
|
|
57
59
|
operations: Record<string, OperationTiming>;
|
|
58
60
|
};
|
|
59
61
|
|
|
62
|
+
export const formatReactRouterPerformanceReport = (
|
|
63
|
+
report: ReactRouterPerformanceReport
|
|
64
|
+
): string => `[react-router:performance] ${JSON.stringify(report)}`;
|
|
65
|
+
|
|
60
66
|
export type ReactRouterPerformanceProfiler = {
|
|
61
67
|
record<T>(
|
|
62
68
|
environment: string | undefined,
|
|
@@ -72,7 +78,10 @@ export type ReactRouterPerformanceProfiler = {
|
|
|
72
78
|
): T;
|
|
73
79
|
flush(
|
|
74
80
|
environment: string | undefined,
|
|
75
|
-
details?: Pick<
|
|
81
|
+
details?: Pick<
|
|
82
|
+
ReactRouterPerformanceReport,
|
|
83
|
+
'compilerLifecycleMs' | 'partial' | 'workerId'
|
|
84
|
+
>
|
|
76
85
|
): void;
|
|
77
86
|
};
|
|
78
87
|
|
|
@@ -247,7 +256,7 @@ export const createReactRouterPerformanceProfiler = ({
|
|
|
247
256
|
...details,
|
|
248
257
|
operations,
|
|
249
258
|
};
|
|
250
|
-
log(
|
|
259
|
+
log(formatReactRouterPerformanceReport(report));
|
|
251
260
|
timingsByEnvironment.delete(resolvedEnvironment);
|
|
252
261
|
},
|
|
253
262
|
};
|