rsbuild-plugin-react-router 0.2.0 → 0.3.1
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 +213 -201
- package/dist/451.js +1103 -0
- package/dist/bounded-cache.d.ts +1 -0
- package/dist/build-manifest.d.ts +7 -4
- package/dist/build-output-transforms.d.ts +30 -0
- package/dist/concurrency.d.ts +3 -0
- package/dist/config-imports.d.ts +10 -0
- package/dist/constants.d.ts +3 -0
- package/dist/dev-background-resources.d.ts +38 -0
- package/dist/dev-generation.d.ts +25 -0
- package/dist/dev-runtime-artifacts.d.ts +47 -0
- package/dist/dev-runtime-compilation.d.ts +47 -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 +16 -2
- package/dist/effect-runtime.d.ts +18 -0
- package/dist/export-utils.d.ts +15 -7
- package/dist/index.cjs +13775 -1412
- package/dist/index.d.ts +8 -1
- package/dist/index.js +9429 -1501
- package/dist/lazy-compilation-prewarm.d.ts +25 -0
- package/dist/lazy-compilation.d.ts +6 -0
- package/dist/manifest.d.ts +48 -10
- 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 +29 -0
- package/dist/performance.d.ts +26 -0
- package/dist/plugin-utils.d.ts +2 -12
- package/dist/prerender-build.d.ts +36 -0
- package/dist/prerender.d.ts +27 -2
- package/dist/react-router-config.d.ts +15 -5
- 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-build-resolution.d.ts +3 -0
- package/dist/server-utils.d.ts +3 -2
- package/dist/ssr-externals.d.ts +1 -0
- package/dist/templates/entry.server.cjs +3 -3
- package/dist/templates/entry.server.js +3 -3
- package/dist/typegen.d.ts +15 -0
- package/dist/types.d.ts +41 -14
- 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 +24 -19
- package/src/bounded-cache.ts +18 -0
- package/src/build-manifest.ts +205 -0
- package/src/build-output-transforms.ts +273 -0
- package/src/concurrency.ts +15 -0
- package/src/config-imports.ts +83 -0
- package/src/constants.ts +91 -0
- package/src/dev-background-resources.ts +255 -0
- package/src/dev-generation.ts +690 -0
- package/src/dev-runtime-artifacts.ts +239 -0
- package/src/dev-runtime-compilation.ts +171 -0
- package/src/dev-runtime-controller.ts +542 -0
- package/src/dev-runtime-session.ts +191 -0
- package/src/dev-server.ts +88 -0
- package/src/effect-runtime.ts +130 -0
- package/src/export-utils.ts +278 -0
- package/src/index.ts +990 -0
- package/src/lazy-compilation-prewarm.ts +279 -0
- package/src/lazy-compilation.ts +101 -0
- package/src/manifest.ts +591 -0
- package/src/modify-browser-manifest.ts +246 -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 +458 -0
- package/src/performance.ts +254 -0
- package/src/plugin-utils.ts +82 -0
- package/src/prerender-build.ts +687 -0
- package/src/prerender.ts +349 -0
- package/src/react-router-config.ts +245 -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 +357 -0
- package/src/server-build-plan.ts +91 -0
- package/src/server-build-resolution.ts +131 -0
- package/src/server-utils.ts +111 -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 +178 -0
- package/src/types.ts +92 -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
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
import type { Route, PluginOptions } from './types.js';
|
|
2
|
+
import type { RsbuildPluginAPI, Rspack } from '@rsbuild/core';
|
|
3
|
+
import {
|
|
4
|
+
createReactRouterManifestStats,
|
|
5
|
+
generateReactRouterManifestForDev,
|
|
6
|
+
getReactRouterManifestChunkNames,
|
|
7
|
+
getReactRouterManifestForDev,
|
|
8
|
+
getReactRouterManifestPath,
|
|
9
|
+
} from './manifest.js';
|
|
10
|
+
import { combineURLs } from './plugin-utils.js';
|
|
11
|
+
import jsesc from 'jsesc';
|
|
12
|
+
|
|
13
|
+
type StatsAssetWithIntegrity = {
|
|
14
|
+
name?: string;
|
|
15
|
+
integrity?: unknown;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
type StatsWithIntegrity = {
|
|
19
|
+
assets?: StatsAssetWithIntegrity[];
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
type CompilationAssetWithIntegrity = {
|
|
23
|
+
name: string;
|
|
24
|
+
info?: {
|
|
25
|
+
integrity?: unknown;
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
type CompilationWithIntegrityAssets =
|
|
30
|
+
| {
|
|
31
|
+
getAssets?: () => readonly CompilationAssetWithIntegrity[];
|
|
32
|
+
}
|
|
33
|
+
| Pick<Rspack.Compilation, 'getAssets'>;
|
|
34
|
+
|
|
35
|
+
type ModifyBrowserManifestOptions = {
|
|
36
|
+
future?: { unstable_subResourceIntegrity?: boolean };
|
|
37
|
+
subResourceIntegrity?: boolean;
|
|
38
|
+
manifestChunkNames?: ReadonlySet<string>;
|
|
39
|
+
onManifest?: (
|
|
40
|
+
manifest: Awaited<ReturnType<typeof getReactRouterManifestForDev>>,
|
|
41
|
+
sri: Record<string, string> | true | undefined,
|
|
42
|
+
moduleExportsByRouteId: Awaited<
|
|
43
|
+
ReturnType<typeof generateReactRouterManifestForDev>
|
|
44
|
+
>['moduleExportsByRouteId'],
|
|
45
|
+
context: {
|
|
46
|
+
compilation: Rspack.Compilation;
|
|
47
|
+
manifestStats: ReturnType<typeof createReactRouterManifestStats>;
|
|
48
|
+
}
|
|
49
|
+
) => void;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
type ProcessAssetsApi = Pick<RsbuildPluginAPI, 'processAssets'>;
|
|
53
|
+
type AssetPrefixInput = string | (() => string);
|
|
54
|
+
type ReactRouterManifest = Awaited<
|
|
55
|
+
ReturnType<typeof getReactRouterManifestForDev>
|
|
56
|
+
>;
|
|
57
|
+
type RouteManifestModuleExports = Awaited<
|
|
58
|
+
ReturnType<typeof generateReactRouterManifestForDev>
|
|
59
|
+
>['moduleExportsByRouteId'];
|
|
60
|
+
type GeneratedManifest = {
|
|
61
|
+
manifest: ReactRouterManifest;
|
|
62
|
+
moduleExportsByRouteId: RouteManifestModuleExports;
|
|
63
|
+
manifestStats: ReturnType<typeof createReactRouterManifestStats>;
|
|
64
|
+
assetPrefix: string;
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const BROWSER_MANIFEST_ASSET =
|
|
68
|
+
'static/js/virtual/react-router/browser-manifest.js';
|
|
69
|
+
const ABSOLUTE_URL_RE = /^[a-zA-Z][a-zA-Z\d+\-.]*:/;
|
|
70
|
+
|
|
71
|
+
const toManifestAssetUrl = (assetPrefix: string, assetName: string) => {
|
|
72
|
+
if (
|
|
73
|
+
ABSOLUTE_URL_RE.test(assetName) ||
|
|
74
|
+
assetName.startsWith('//') ||
|
|
75
|
+
assetName.startsWith('/')
|
|
76
|
+
) {
|
|
77
|
+
return assetName;
|
|
78
|
+
}
|
|
79
|
+
return combineURLs(assetPrefix, assetName);
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const addIntegrity = (
|
|
83
|
+
sri: Record<string, string>,
|
|
84
|
+
assetPrefix: string,
|
|
85
|
+
assetName: unknown,
|
|
86
|
+
integrity: unknown
|
|
87
|
+
) => {
|
|
88
|
+
if (typeof assetName !== 'string' || typeof integrity !== 'string') {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
sri[toManifestAssetUrl(assetPrefix, assetName)] = integrity;
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
export const collectSubresourceIntegrity = (
|
|
95
|
+
stats: StatsWithIntegrity | undefined,
|
|
96
|
+
compilation: CompilationWithIntegrityAssets | undefined,
|
|
97
|
+
assetPrefix = '/'
|
|
98
|
+
): Record<string, string> | undefined => {
|
|
99
|
+
const sri: Record<string, string> = {};
|
|
100
|
+
|
|
101
|
+
for (const asset of stats?.assets ?? []) {
|
|
102
|
+
addIntegrity(sri, assetPrefix, asset.name, asset.integrity);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (typeof compilation?.getAssets === 'function') {
|
|
106
|
+
const assets =
|
|
107
|
+
compilation.getAssets() as readonly CompilationAssetWithIntegrity[];
|
|
108
|
+
for (const asset of assets) {
|
|
109
|
+
addIntegrity(sri, assetPrefix, asset.name, asset.info?.integrity);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return Object.keys(sri).length > 0 ? sri : undefined;
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
export function registerModifyBrowserManifestAssets(
|
|
117
|
+
api: ProcessAssetsApi,
|
|
118
|
+
routes: Record<string, Route>,
|
|
119
|
+
pluginOptions: PluginOptions,
|
|
120
|
+
appDirectory: string,
|
|
121
|
+
assetPrefix: AssetPrefixInput = '/',
|
|
122
|
+
routeChunkOptions?: Parameters<typeof getReactRouterManifestForDev>[5],
|
|
123
|
+
options?: ModifyBrowserManifestOptions
|
|
124
|
+
): void {
|
|
125
|
+
const getAssetPrefix =
|
|
126
|
+
typeof assetPrefix === 'function' ? assetPrefix : () => assetPrefix;
|
|
127
|
+
const manifestChunkNames =
|
|
128
|
+
options?.manifestChunkNames ??
|
|
129
|
+
getReactRouterManifestChunkNames(
|
|
130
|
+
routes,
|
|
131
|
+
routeChunkOptions?.splitRouteModules
|
|
132
|
+
);
|
|
133
|
+
const finalizeSri = Boolean(
|
|
134
|
+
routeChunkOptions?.isBuild &&
|
|
135
|
+
(options?.subResourceIntegrity ??
|
|
136
|
+
options?.future?.unstable_subResourceIntegrity)
|
|
137
|
+
);
|
|
138
|
+
const generatedManifests = finalizeSri
|
|
139
|
+
? new WeakMap<Rspack.Compilation, GeneratedManifest>()
|
|
140
|
+
: undefined;
|
|
141
|
+
|
|
142
|
+
api.processAssets(
|
|
143
|
+
{ stage: 'additions', environments: ['web'] },
|
|
144
|
+
async ({ assets, sources, compilation }) => {
|
|
145
|
+
const currentAssetPrefix = getAssetPrefix();
|
|
146
|
+
const stats = createReactRouterManifestStats(
|
|
147
|
+
compilation,
|
|
148
|
+
manifestChunkNames
|
|
149
|
+
);
|
|
150
|
+
const { manifest, moduleExportsByRouteId } =
|
|
151
|
+
await generateReactRouterManifestForDev(
|
|
152
|
+
routes,
|
|
153
|
+
pluginOptions,
|
|
154
|
+
stats,
|
|
155
|
+
appDirectory,
|
|
156
|
+
currentAssetPrefix,
|
|
157
|
+
routeChunkOptions
|
|
158
|
+
);
|
|
159
|
+
const manifestForBrowser = finalizeSri
|
|
160
|
+
? { ...manifest, sri: true as const }
|
|
161
|
+
: manifest;
|
|
162
|
+
|
|
163
|
+
const browserManifestAsset = assets[BROWSER_MANIFEST_ASSET];
|
|
164
|
+
if (browserManifestAsset) {
|
|
165
|
+
const originalSource = browserManifestAsset.source().toString();
|
|
166
|
+
const serializedManifest = jsesc(manifestForBrowser, { es6: true });
|
|
167
|
+
const newSource = originalSource.replace(
|
|
168
|
+
/["'`]PLACEHOLDER["'`]/,
|
|
169
|
+
() => serializedManifest
|
|
170
|
+
);
|
|
171
|
+
compilation.updateAsset(
|
|
172
|
+
BROWSER_MANIFEST_ASSET,
|
|
173
|
+
new sources.RawSource(newSource)
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (routeChunkOptions?.isBuild) {
|
|
178
|
+
const entryAssets = stats?.assetsByChunkName?.['entry.client'];
|
|
179
|
+
const entryJsAssets =
|
|
180
|
+
entryAssets?.filter(asset => asset.endsWith('.js')) || [];
|
|
181
|
+
const manifestPath = getReactRouterManifestPath({
|
|
182
|
+
version: manifest.version,
|
|
183
|
+
isBuild: true,
|
|
184
|
+
entryModulePath: entryJsAssets[0],
|
|
185
|
+
});
|
|
186
|
+
const manifestSource = `window.__reactRouterManifest=${jsesc(
|
|
187
|
+
manifestForBrowser,
|
|
188
|
+
{ es6: true }
|
|
189
|
+
)};`;
|
|
190
|
+
const source = new sources.RawSource(manifestSource);
|
|
191
|
+
if (compilation.getAsset(manifestPath)) {
|
|
192
|
+
compilation.updateAsset(manifestPath, source);
|
|
193
|
+
} else {
|
|
194
|
+
compilation.emitAsset(manifestPath, source);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
if (generatedManifests) {
|
|
199
|
+
generatedManifests.set(compilation, {
|
|
200
|
+
manifest,
|
|
201
|
+
moduleExportsByRouteId,
|
|
202
|
+
manifestStats: stats,
|
|
203
|
+
assetPrefix: currentAssetPrefix,
|
|
204
|
+
});
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
options?.onManifest?.(manifest, undefined, moduleExportsByRouteId, {
|
|
209
|
+
compilation,
|
|
210
|
+
manifestStats: stats,
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
);
|
|
214
|
+
|
|
215
|
+
if (generatedManifests) {
|
|
216
|
+
api.processAssets(
|
|
217
|
+
{ stage: 'report', environments: ['web'] },
|
|
218
|
+
({ compilation }) => {
|
|
219
|
+
const generatedManifest = generatedManifests.get(compilation);
|
|
220
|
+
if (!generatedManifest) {
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
generatedManifests.delete(compilation);
|
|
225
|
+
const sri =
|
|
226
|
+
collectSubresourceIntegrity(
|
|
227
|
+
undefined,
|
|
228
|
+
compilation,
|
|
229
|
+
generatedManifest.assetPrefix
|
|
230
|
+
) ?? true;
|
|
231
|
+
options?.onManifest?.(
|
|
232
|
+
{
|
|
233
|
+
...generatedManifest.manifest,
|
|
234
|
+
sri,
|
|
235
|
+
},
|
|
236
|
+
sri,
|
|
237
|
+
generatedManifest.moduleExportsByRouteId,
|
|
238
|
+
{
|
|
239
|
+
compilation,
|
|
240
|
+
manifestStats: generatedManifest.manifestStats,
|
|
241
|
+
}
|
|
242
|
+
);
|
|
243
|
+
}
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
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
|
+
};
|
|
@@ -0,0 +1,82 @@
|
|
|
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
|
+
);
|