rsbuild-plugin-react-router 0.4.1 → 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 -334
- package/dist/index.js +129 -406
- 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 -56
- 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
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { threadId } from 'node:worker_threads';
|
|
2
|
+
import remapping, { type SourceMapInput } from '@jridgewell/remapping';
|
|
3
|
+
import type { LoaderDefinition } from '@rspack/core';
|
|
4
|
+
import { createReactRouterPerformanceProfiler } from './performance.js';
|
|
5
|
+
import { executeRouteTransformTask } from './route-transform-tasks.js';
|
|
6
|
+
|
|
7
|
+
export type RouteModuleTransformLoaderOptions = {
|
|
8
|
+
environmentName: string;
|
|
9
|
+
performanceScopeId: string;
|
|
10
|
+
logPerformance: boolean;
|
|
11
|
+
ssr: boolean;
|
|
12
|
+
isBuild: boolean;
|
|
13
|
+
isSpaMode: boolean;
|
|
14
|
+
rootRoutePath: string | null;
|
|
15
|
+
devHmr: boolean;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
type LoaderContextWithSourceMap = ThisParameterType<
|
|
19
|
+
LoaderDefinition<RouteModuleTransformLoaderOptions>
|
|
20
|
+
> & {
|
|
21
|
+
sourceMap?: boolean;
|
|
22
|
+
};
|
|
23
|
+
type LoaderInputSourceMap = Parameters<
|
|
24
|
+
LoaderDefinition<RouteModuleTransformLoaderOptions>
|
|
25
|
+
>[1];
|
|
26
|
+
type RawLoaderSourceMap = Exclude<LoaderInputSourceMap, string | undefined>;
|
|
27
|
+
|
|
28
|
+
const LOADER_PERFORMANCE_FLUSH_DELAY_MS = 50;
|
|
29
|
+
const performanceWorkerId = `process-${process.pid}:thread-${threadId}`;
|
|
30
|
+
|
|
31
|
+
const composeSourceMaps = (
|
|
32
|
+
generatedMap: SourceMapInput,
|
|
33
|
+
inputSourceMap: SourceMapInput
|
|
34
|
+
): RawLoaderSourceMap =>
|
|
35
|
+
JSON.parse(
|
|
36
|
+
remapping([generatedMap, inputSourceMap], () => null).toString()
|
|
37
|
+
) as RawLoaderSourceMap;
|
|
38
|
+
|
|
39
|
+
const performanceProfilersByScope = new Map<
|
|
40
|
+
string,
|
|
41
|
+
Map<string, ReturnType<typeof createReactRouterPerformanceProfiler>>
|
|
42
|
+
>();
|
|
43
|
+
let performanceFlushTimer: ReturnType<typeof setTimeout> | undefined;
|
|
44
|
+
|
|
45
|
+
const getPerformanceProfiler = (
|
|
46
|
+
scopeId: string,
|
|
47
|
+
environment: string | undefined
|
|
48
|
+
): ReturnType<typeof createReactRouterPerformanceProfiler> => {
|
|
49
|
+
let profilers = performanceProfilersByScope.get(scopeId);
|
|
50
|
+
if (!profilers) {
|
|
51
|
+
profilers = new Map();
|
|
52
|
+
performanceProfilersByScope.set(scopeId, profilers);
|
|
53
|
+
}
|
|
54
|
+
const environmentKey = environment ?? 'unknown';
|
|
55
|
+
let profiler = profilers.get(environmentKey);
|
|
56
|
+
if (!profiler) {
|
|
57
|
+
profiler = createReactRouterPerformanceProfiler({
|
|
58
|
+
enabled: true,
|
|
59
|
+
log: message => console.info(message),
|
|
60
|
+
});
|
|
61
|
+
profilers.set(environmentKey, profiler);
|
|
62
|
+
}
|
|
63
|
+
return profiler;
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export const flushRouteModuleTransformLoaderPerformance = (): void => {
|
|
67
|
+
if (performanceFlushTimer) {
|
|
68
|
+
clearTimeout(performanceFlushTimer);
|
|
69
|
+
performanceFlushTimer = undefined;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
for (const profilers of performanceProfilersByScope.values()) {
|
|
73
|
+
for (const [environment, profiler] of profilers) {
|
|
74
|
+
profiler.flush(environment === 'unknown' ? undefined : environment, {
|
|
75
|
+
partial: true,
|
|
76
|
+
workerId: performanceWorkerId,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
performanceProfilersByScope.clear();
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
const schedulePerformanceFlush = (): void => {
|
|
84
|
+
if (performanceFlushTimer) {
|
|
85
|
+
clearTimeout(performanceFlushTimer);
|
|
86
|
+
}
|
|
87
|
+
performanceFlushTimer = setTimeout(
|
|
88
|
+
flushRouteModuleTransformLoaderPerformance,
|
|
89
|
+
LOADER_PERFORMANCE_FLUSH_DELAY_MS
|
|
90
|
+
);
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
process.once('beforeExit', flushRouteModuleTransformLoaderPerformance);
|
|
94
|
+
|
|
95
|
+
const routeModuleTransformLoader: LoaderDefinition<RouteModuleTransformLoaderOptions> =
|
|
96
|
+
async function routeModuleTransformLoader(
|
|
97
|
+
this: LoaderContextWithSourceMap,
|
|
98
|
+
source,
|
|
99
|
+
inputSourceMap
|
|
100
|
+
) {
|
|
101
|
+
const callback = this.async();
|
|
102
|
+
const options = this.getOptions();
|
|
103
|
+
|
|
104
|
+
const transform = () =>
|
|
105
|
+
executeRouteTransformTask({
|
|
106
|
+
kind: 'routeModule',
|
|
107
|
+
code: String(source),
|
|
108
|
+
resource: this.resource,
|
|
109
|
+
resourcePath: this.resourcePath,
|
|
110
|
+
environmentName: options.environmentName,
|
|
111
|
+
sourceMaps: Boolean(this.sourceMap),
|
|
112
|
+
ssr: options.ssr,
|
|
113
|
+
isBuild: options.isBuild,
|
|
114
|
+
isSpaMode: options.isSpaMode,
|
|
115
|
+
rootRoutePath: options.rootRoutePath,
|
|
116
|
+
devHmr: options.devHmr,
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
try {
|
|
120
|
+
const result = options.logPerformance
|
|
121
|
+
? await getPerformanceProfiler(
|
|
122
|
+
options.performanceScopeId,
|
|
123
|
+
options.environmentName
|
|
124
|
+
).record(
|
|
125
|
+
options.environmentName,
|
|
126
|
+
'route:module',
|
|
127
|
+
this.resource,
|
|
128
|
+
transform
|
|
129
|
+
)
|
|
130
|
+
: await transform();
|
|
131
|
+
|
|
132
|
+
const outputSourceMap =
|
|
133
|
+
result.map && inputSourceMap
|
|
134
|
+
? composeSourceMaps(
|
|
135
|
+
result.map as SourceMapInput,
|
|
136
|
+
inputSourceMap as SourceMapInput
|
|
137
|
+
)
|
|
138
|
+
: result.map;
|
|
139
|
+
callback(null, result.code, outputSourceMap ?? undefined);
|
|
140
|
+
} catch (error) {
|
|
141
|
+
callback(error instanceof Error ? error : new Error(String(error)));
|
|
142
|
+
} finally {
|
|
143
|
+
if (options.logPerformance) {
|
|
144
|
+
schedulePerformanceFlush();
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
export default routeModuleTransformLoader;
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { fileURLToPath } from 'node:url';
|
|
2
|
+
import type { Rspack } from '@rsbuild/core';
|
|
3
|
+
import type { RouteModuleTransformLoaderOptions } from './route-module-transform-loader.js';
|
|
4
|
+
import type { PluginOptions, Route } from './types.js';
|
|
5
|
+
|
|
6
|
+
const routeModuleTransformLoaderPath = fileURLToPath(
|
|
7
|
+
new URL('./route-module-transform-loader.js', import.meta.url)
|
|
8
|
+
);
|
|
9
|
+
|
|
10
|
+
const getRouteModuleTransformParallel = (
|
|
11
|
+
parallelRouteTransform: PluginOptions['parallelRouteTransform']
|
|
12
|
+
): Rspack.RuleSetLoaderWithOptions['parallel'] => {
|
|
13
|
+
if (
|
|
14
|
+
parallelRouteTransform === undefined ||
|
|
15
|
+
parallelRouteTransform === false
|
|
16
|
+
) {
|
|
17
|
+
return undefined;
|
|
18
|
+
}
|
|
19
|
+
if (parallelRouteTransform === true) {
|
|
20
|
+
return true;
|
|
21
|
+
}
|
|
22
|
+
if (typeof parallelRouteTransform === 'number') {
|
|
23
|
+
if (
|
|
24
|
+
!Number.isInteger(parallelRouteTransform) ||
|
|
25
|
+
parallelRouteTransform < 1
|
|
26
|
+
) {
|
|
27
|
+
throw new Error(
|
|
28
|
+
'[react-router] parallelRouteTransform must be true, false, or a positive integer.'
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
return { maxWorkers: parallelRouteTransform };
|
|
32
|
+
}
|
|
33
|
+
throw new Error(
|
|
34
|
+
'[react-router] parallelRouteTransform must be true, false, or a positive integer.'
|
|
35
|
+
);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export const shouldUseRouteModuleTransformLoader = (
|
|
39
|
+
parallelRouteTransform: PluginOptions['parallelRouteTransform']
|
|
40
|
+
): boolean =>
|
|
41
|
+
getRouteModuleTransformParallel(parallelRouteTransform) !== undefined;
|
|
42
|
+
|
|
43
|
+
const createRouteModuleTransformUse = (
|
|
44
|
+
options: RouteModuleTransformLoaderOptions,
|
|
45
|
+
parallelRouteTransform: PluginOptions['parallelRouteTransform']
|
|
46
|
+
): Rspack.RuleSetLoaderWithOptions => {
|
|
47
|
+
const parallel = getRouteModuleTransformParallel(parallelRouteTransform);
|
|
48
|
+
return {
|
|
49
|
+
loader: routeModuleTransformLoaderPath,
|
|
50
|
+
options,
|
|
51
|
+
...(parallel ? { parallel } : {}),
|
|
52
|
+
};
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export const registerRouteModuleTransformRules = (
|
|
56
|
+
rspackConfig: Rspack.Configuration,
|
|
57
|
+
{
|
|
58
|
+
environmentName,
|
|
59
|
+
ssr,
|
|
60
|
+
isBuild,
|
|
61
|
+
isSpaMode,
|
|
62
|
+
rootRoutePath,
|
|
63
|
+
devHmr,
|
|
64
|
+
logPerformance,
|
|
65
|
+
routeByFilePath,
|
|
66
|
+
parallelRouteTransform,
|
|
67
|
+
}: {
|
|
68
|
+
environmentName: string;
|
|
69
|
+
ssr: boolean;
|
|
70
|
+
isBuild: boolean;
|
|
71
|
+
isSpaMode: boolean;
|
|
72
|
+
rootRoutePath: string | null;
|
|
73
|
+
devHmr: boolean;
|
|
74
|
+
logPerformance: boolean;
|
|
75
|
+
routeByFilePath: Map<string, Route>;
|
|
76
|
+
parallelRouteTransform: PluginOptions['parallelRouteTransform'];
|
|
77
|
+
}
|
|
78
|
+
): void => {
|
|
79
|
+
const routeModuleTransformUse = createRouteModuleTransformUse(
|
|
80
|
+
{
|
|
81
|
+
environmentName,
|
|
82
|
+
performanceScopeId: [
|
|
83
|
+
environmentName,
|
|
84
|
+
isBuild ? 'build' : 'dev',
|
|
85
|
+
ssr ? 'ssr' : 'spa',
|
|
86
|
+
rootRoutePath ?? 'rootless',
|
|
87
|
+
].join(':'),
|
|
88
|
+
logPerformance,
|
|
89
|
+
ssr,
|
|
90
|
+
isBuild,
|
|
91
|
+
isSpaMode,
|
|
92
|
+
rootRoutePath,
|
|
93
|
+
devHmr,
|
|
94
|
+
},
|
|
95
|
+
parallelRouteTransform
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
rspackConfig.module ??= {};
|
|
99
|
+
rspackConfig.module.rules ??= [];
|
|
100
|
+
rspackConfig.module.rules.push(
|
|
101
|
+
{
|
|
102
|
+
resourceQuery: /\?react-router-route/,
|
|
103
|
+
enforce: 'post',
|
|
104
|
+
use: [routeModuleTransformUse],
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
test: path => routeByFilePath.has(path),
|
|
108
|
+
resourceQuery: {
|
|
109
|
+
not: /__react-router-build-client-route|react-router-route|route-chunk=/,
|
|
110
|
+
},
|
|
111
|
+
enforce: 'post',
|
|
112
|
+
use: [routeModuleTransformUse],
|
|
113
|
+
}
|
|
114
|
+
);
|
|
115
|
+
};
|
|
@@ -24,10 +24,7 @@ import {
|
|
|
24
24
|
type RouteChunkCache,
|
|
25
25
|
type RouteChunkConfig,
|
|
26
26
|
} from './route-chunks.js';
|
|
27
|
-
import {
|
|
28
|
-
getProgram,
|
|
29
|
-
type AnyNode,
|
|
30
|
-
} from './route-ast.js';
|
|
27
|
+
import { getProgram, type AnyNode } from './route-ast.js';
|
|
31
28
|
|
|
32
29
|
export type RouteTransformResult = {
|
|
33
30
|
code: string;
|
|
@@ -88,6 +85,10 @@ export type RouteTransformTaskOptions = {
|
|
|
88
85
|
routeChunkCache?: RouteChunkCache;
|
|
89
86
|
};
|
|
90
87
|
|
|
88
|
+
export type RouteTransformRunner = (
|
|
89
|
+
task: RouteTransformTask
|
|
90
|
+
) => Promise<RouteTransformResult>;
|
|
91
|
+
|
|
91
92
|
const defaultRouteChunkCache: RouteChunkCache = new Map();
|
|
92
93
|
|
|
93
94
|
const getRouteChunkCache = (options?: RouteTransformTaskOptions) =>
|
package/src/types.ts
CHANGED
|
@@ -57,11 +57,10 @@ export type PluginOptions = {
|
|
|
57
57
|
logPerformance?: boolean;
|
|
58
58
|
|
|
59
59
|
/**
|
|
60
|
-
* Run route transforms
|
|
61
|
-
* Pass `true` to
|
|
62
|
-
* the worker count, or `false` to disable.
|
|
63
|
-
* @default
|
|
64
|
-
* pool uses available CPU cores minus 2.
|
|
60
|
+
* Run route module transforms with Rspack's parallel loader workers.
|
|
61
|
+
* Pass `true` to use Rspack's default worker count, a positive integer to set
|
|
62
|
+
* the maximum worker count, or `false` to disable.
|
|
63
|
+
* @default false
|
|
65
64
|
*/
|
|
66
65
|
parallelRouteTransform?: boolean | number;
|
|
67
66
|
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import type { RouteTransformResult, RouteTransformTask } from './route-transform-tasks.js';
|
|
2
|
-
type WithoutRequiredSource<Task> = Task extends RouteTransformTask ? Omit<Task, 'code'> & {
|
|
3
|
-
code?: string;
|
|
4
|
-
} : never;
|
|
5
|
-
export type CachedRouteTransformTask = WithoutRequiredSource<RouteTransformTask>;
|
|
6
|
-
export type WorkerRequest = {
|
|
7
|
-
id: number;
|
|
8
|
-
task: RouteTransformTask | CachedRouteTransformTask;
|
|
9
|
-
sourceCacheKey?: string;
|
|
10
|
-
};
|
|
11
|
-
export type WorkerErrorPayload = {
|
|
12
|
-
name?: string;
|
|
13
|
-
message: string;
|
|
14
|
-
stack?: string;
|
|
15
|
-
};
|
|
16
|
-
export type WorkerResponse = {
|
|
17
|
-
id: number;
|
|
18
|
-
ok: true;
|
|
19
|
-
result: RouteTransformResult;
|
|
20
|
-
} | {
|
|
21
|
-
id: number;
|
|
22
|
-
ok: false;
|
|
23
|
-
error: WorkerErrorPayload;
|
|
24
|
-
};
|
|
25
|
-
export {};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { parentPort } from "node:worker_threads";
|
|
2
|
-
import { setBoundedCacheEntry, executeRouteTransformTask } from "./451.js";
|
|
3
|
-
if (!parentPort) throw Error('parallel route transform worker requires parentPort');
|
|
4
|
-
let sourceCache = new Map();
|
|
5
|
-
parentPort.on('message', async ({ id, task, sourceCacheKey })=>{
|
|
6
|
-
try {
|
|
7
|
-
let hydratedTask = (({ task, sourceCacheKey })=>{
|
|
8
|
-
if (!sourceCacheKey) return task;
|
|
9
|
-
if ('string' == typeof task.code) return setBoundedCacheEntry(sourceCache, sourceCacheKey, task.code, 2048), task;
|
|
10
|
-
let code = sourceCache.get(sourceCacheKey);
|
|
11
|
-
if (void 0 === code) throw Error(`Missing cached route transform source for ${sourceCacheKey}.`);
|
|
12
|
-
return {
|
|
13
|
-
...task,
|
|
14
|
-
code
|
|
15
|
-
};
|
|
16
|
-
})({
|
|
17
|
-
task,
|
|
18
|
-
sourceCacheKey
|
|
19
|
-
}), result = await executeRouteTransformTask(hydratedTask);
|
|
20
|
-
parentPort?.postMessage({
|
|
21
|
-
id,
|
|
22
|
-
ok: !0,
|
|
23
|
-
result
|
|
24
|
-
});
|
|
25
|
-
} catch (error) {
|
|
26
|
-
parentPort?.postMessage({
|
|
27
|
-
id,
|
|
28
|
-
ok: !1,
|
|
29
|
-
error: error instanceof Error ? {
|
|
30
|
-
name: error.name,
|
|
31
|
-
message: error.message,
|
|
32
|
-
stack: error.stack
|
|
33
|
-
} : {
|
|
34
|
-
message: String(error)
|
|
35
|
-
}
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
|
-
});
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { type RouteTransformResult, type RouteTransformTask, type RouteTransformTaskOptions } from './route-transform-tasks.js';
|
|
2
|
-
import type { PluginOptions } from './types.js';
|
|
3
|
-
import type { WorkerRequest, WorkerResponse } from './parallel-route-transform-protocol.js';
|
|
4
|
-
export type ParallelRouteTransformConfig = NonNullable<PluginOptions['parallelRouteTransform']> extends infer Config ? Exclude<Config, false> : never;
|
|
5
|
-
export type RouteTransformExecutorOptions = RouteTransformTaskOptions & {
|
|
6
|
-
parallelRouteTransform?: PluginOptions['parallelRouteTransform'];
|
|
7
|
-
splitRouteModules?: boolean;
|
|
8
|
-
isBuild?: boolean;
|
|
9
|
-
};
|
|
10
|
-
export type RouteTransformExecutor = {
|
|
11
|
-
run: (task: RouteTransformTask) => Promise<RouteTransformResult>;
|
|
12
|
-
prewarm: () => void;
|
|
13
|
-
close: () => Promise<void>;
|
|
14
|
-
};
|
|
15
|
-
type RouteTransformWorker = {
|
|
16
|
-
on(event: 'message', handler: (response: WorkerResponse) => void): unknown;
|
|
17
|
-
on(event: 'error', handler: (error: Error) => void): unknown;
|
|
18
|
-
on(event: 'exit', handler: (code: number) => void): unknown;
|
|
19
|
-
postMessage(message: WorkerRequest): void;
|
|
20
|
-
terminate(): Promise<number> | number;
|
|
21
|
-
};
|
|
22
|
-
type RouteTransformWorkerFactory = () => RouteTransformWorker;
|
|
23
|
-
export declare const getDefaultWorkerCount: (cpuCount?: number, { isBuild }?: {
|
|
24
|
-
isBuild?: boolean;
|
|
25
|
-
}) => number;
|
|
26
|
-
export declare const shouldParallelizeRouteTransforms: (routeCount: number) => boolean;
|
|
27
|
-
export declare const createRouteTransformExecutor: ({ parallelRouteTransform, routeChunkCache, splitRouteModules, isBuild, }?: RouteTransformExecutorOptions) => RouteTransformExecutor;
|
|
28
|
-
export declare const createRouteTransformExecutorForTesting: (options: RouteTransformExecutorOptions, createWorker: RouteTransformWorkerFactory) => RouteTransformExecutor;
|
|
29
|
-
export {};
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
RouteTransformResult,
|
|
3
|
-
RouteTransformTask,
|
|
4
|
-
} from './route-transform-tasks.js';
|
|
5
|
-
|
|
6
|
-
type WithoutRequiredSource<Task> = Task extends RouteTransformTask
|
|
7
|
-
? Omit<Task, 'code'> & { code?: string }
|
|
8
|
-
: never;
|
|
9
|
-
|
|
10
|
-
export type CachedRouteTransformTask =
|
|
11
|
-
WithoutRequiredSource<RouteTransformTask>;
|
|
12
|
-
|
|
13
|
-
export type WorkerRequest = {
|
|
14
|
-
id: number;
|
|
15
|
-
task: RouteTransformTask | CachedRouteTransformTask;
|
|
16
|
-
sourceCacheKey?: string;
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
export type WorkerErrorPayload = {
|
|
20
|
-
name?: string;
|
|
21
|
-
message: string;
|
|
22
|
-
stack?: string;
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
export type WorkerResponse =
|
|
26
|
-
| {
|
|
27
|
-
id: number;
|
|
28
|
-
ok: true;
|
|
29
|
-
result: RouteTransformResult;
|
|
30
|
-
}
|
|
31
|
-
| {
|
|
32
|
-
id: number;
|
|
33
|
-
ok: false;
|
|
34
|
-
error: WorkerErrorPayload;
|
|
35
|
-
};
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
import { parentPort } from 'node:worker_threads';
|
|
2
|
-
import { setBoundedCacheEntry } from './bounded-cache.js';
|
|
3
|
-
import {
|
|
4
|
-
executeRouteTransformTask,
|
|
5
|
-
type RouteTransformTask,
|
|
6
|
-
} from './route-transform-tasks.js';
|
|
7
|
-
import type {
|
|
8
|
-
WorkerErrorPayload,
|
|
9
|
-
WorkerRequest,
|
|
10
|
-
WorkerResponse,
|
|
11
|
-
} from './parallel-route-transform-protocol.js';
|
|
12
|
-
|
|
13
|
-
const serializeError = (error: unknown): WorkerErrorPayload => {
|
|
14
|
-
if (error instanceof Error) {
|
|
15
|
-
return {
|
|
16
|
-
name: error.name,
|
|
17
|
-
message: error.message,
|
|
18
|
-
stack: error.stack,
|
|
19
|
-
};
|
|
20
|
-
}
|
|
21
|
-
return {
|
|
22
|
-
message: String(error),
|
|
23
|
-
};
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
if (!parentPort) {
|
|
27
|
-
throw new Error('parallel route transform worker requires parentPort');
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const MAX_SOURCE_CACHE_ENTRIES = 2048;
|
|
31
|
-
const sourceCache = new Map<string, string>();
|
|
32
|
-
|
|
33
|
-
const hydrateTaskSource = ({
|
|
34
|
-
task,
|
|
35
|
-
sourceCacheKey,
|
|
36
|
-
}: Pick<WorkerRequest, 'task' | 'sourceCacheKey'>): RouteTransformTask => {
|
|
37
|
-
if (!sourceCacheKey) {
|
|
38
|
-
return task as RouteTransformTask;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
if (typeof task.code === 'string') {
|
|
42
|
-
setBoundedCacheEntry(
|
|
43
|
-
sourceCache,
|
|
44
|
-
sourceCacheKey,
|
|
45
|
-
task.code,
|
|
46
|
-
MAX_SOURCE_CACHE_ENTRIES
|
|
47
|
-
);
|
|
48
|
-
return task as RouteTransformTask;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const code = sourceCache.get(sourceCacheKey);
|
|
52
|
-
if (code === undefined) {
|
|
53
|
-
throw new Error(
|
|
54
|
-
`Missing cached route transform source for ${sourceCacheKey}.`
|
|
55
|
-
);
|
|
56
|
-
}
|
|
57
|
-
return {
|
|
58
|
-
...task,
|
|
59
|
-
code,
|
|
60
|
-
} as RouteTransformTask;
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
parentPort.on(
|
|
64
|
-
'message',
|
|
65
|
-
async ({ id, task, sourceCacheKey }: WorkerRequest) => {
|
|
66
|
-
try {
|
|
67
|
-
const hydratedTask = hydrateTaskSource({ task, sourceCacheKey });
|
|
68
|
-
const result = await executeRouteTransformTask(hydratedTask);
|
|
69
|
-
parentPort?.postMessage({
|
|
70
|
-
id,
|
|
71
|
-
ok: true,
|
|
72
|
-
result,
|
|
73
|
-
} satisfies WorkerResponse);
|
|
74
|
-
} catch (error) {
|
|
75
|
-
parentPort?.postMessage({
|
|
76
|
-
id,
|
|
77
|
-
ok: false,
|
|
78
|
-
error: serializeError(error),
|
|
79
|
-
} satisfies WorkerResponse);
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
);
|