rsbuild-plugin-react-router 0.1.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/README.md +185 -204
  2. package/dist/451.js +1087 -0
  3. package/dist/bounded-cache.d.ts +1 -0
  4. package/dist/build-manifest.d.ts +1 -1
  5. package/dist/build-output-transforms.d.ts +30 -0
  6. package/dist/concurrency.d.ts +2 -0
  7. package/dist/config-imports.d.ts +3 -0
  8. package/dist/constants.d.ts +3 -0
  9. package/dist/dev-generation.d.ts +25 -0
  10. package/dist/dev-runtime-artifacts.d.ts +39 -0
  11. package/dist/dev-runtime-compilation.d.ts +32 -0
  12. package/dist/dev-runtime-controller.d.ts +14 -0
  13. package/dist/dev-runtime-session.d.ts +34 -0
  14. package/dist/dev-server.d.ts +11 -2
  15. package/dist/export-utils.d.ts +15 -7
  16. package/dist/index.cjs +3085 -1272
  17. package/dist/index.d.ts +4 -1
  18. package/dist/index.js +2039 -1299
  19. package/dist/lazy-compilation.d.ts +5 -0
  20. package/dist/manifest.d.ts +32 -9
  21. package/dist/modify-browser-manifest.d.ts +30 -13
  22. package/dist/parallel-route-transform-protocol.d.ts +25 -0
  23. package/dist/parallel-route-transform-worker.d.ts +1 -0
  24. package/dist/parallel-route-transform-worker.js +38 -0
  25. package/dist/parallel-route-transforms.d.ts +14 -0
  26. package/dist/performance.d.ts +26 -0
  27. package/dist/plugin-utils.d.ts +2 -12
  28. package/dist/prerender-build.d.ts +32 -0
  29. package/dist/prerender.d.ts +28 -2
  30. package/dist/react-router-config.d.ts +8 -1
  31. package/dist/route-artifacts.d.ts +33 -0
  32. package/dist/route-ast.d.ts +21 -0
  33. package/dist/route-chunks.d.ts +9 -1
  34. package/dist/route-component-transform.d.ts +5 -0
  35. package/dist/route-export-pruning.d.ts +6 -0
  36. package/dist/route-export-resolution.d.ts +5 -0
  37. package/dist/route-transform-tasks.d.ts +47 -0
  38. package/dist/route-watch.d.ts +27 -0
  39. package/dist/server-build-plan.d.ts +22 -0
  40. package/dist/server-utils.d.ts +3 -2
  41. package/dist/templates/entry.client.js +3 -3
  42. package/dist/templates/entry.server.cjs +11 -8
  43. package/dist/templates/entry.server.js +5 -5
  44. package/dist/typegen.d.ts +2 -0
  45. package/dist/types.d.ts +30 -12
  46. package/dist/virtual-modules.d.ts +2 -0
  47. package/dist/warnings/warn-on-client-source-maps.d.ts +1 -0
  48. package/dist/yuku.d.ts +15 -0
  49. package/package.json +26 -22
  50. package/src/bounded-cache.ts +18 -0
  51. package/src/build-manifest.ts +168 -0
  52. package/src/build-output-transforms.ts +273 -0
  53. package/src/concurrency.ts +34 -0
  54. package/src/config-imports.ts +45 -0
  55. package/src/constants.ts +91 -0
  56. package/src/dev-generation.ts +700 -0
  57. package/src/dev-runtime-artifacts.ts +207 -0
  58. package/src/dev-runtime-compilation.ts +92 -0
  59. package/src/dev-runtime-controller.ts +462 -0
  60. package/src/dev-runtime-session.ts +184 -0
  61. package/src/dev-server.ts +58 -0
  62. package/src/export-utils.ts +219 -0
  63. package/src/index.ts +1025 -0
  64. package/src/lazy-compilation.ts +94 -0
  65. package/src/manifest.ts +480 -0
  66. package/src/modify-browser-manifest.ts +245 -0
  67. package/src/parallel-route-transform-protocol.ts +35 -0
  68. package/src/parallel-route-transform-worker.ts +82 -0
  69. package/src/parallel-route-transforms.ts +332 -0
  70. package/src/performance.ts +254 -0
  71. package/src/plugin-utils.ts +82 -0
  72. package/src/prerender-build.ts +623 -0
  73. package/src/prerender.ts +367 -0
  74. package/src/react-router-config.ts +220 -0
  75. package/src/route-artifacts.ts +155 -0
  76. package/src/route-ast.ts +163 -0
  77. package/src/route-chunks.ts +857 -0
  78. package/src/route-component-transform.ts +314 -0
  79. package/src/route-config.ts +106 -0
  80. package/src/route-export-pruning.ts +668 -0
  81. package/src/route-export-resolution.ts +329 -0
  82. package/src/route-transform-tasks.ts +249 -0
  83. package/src/route-watch.ts +322 -0
  84. package/src/server-build-plan.ts +91 -0
  85. package/src/server-utils.ts +210 -0
  86. package/src/ssr-externals.ts +59 -0
  87. package/src/templates/context.ts +12 -0
  88. package/src/templates/entry.client.tsx +12 -0
  89. package/src/templates/entry.server.tsx +76 -0
  90. package/src/typegen.ts +49 -0
  91. package/src/types.ts +82 -0
  92. package/src/validation/validate-plugin-order.ts +76 -0
  93. package/src/virtual-modules.ts +30 -0
  94. package/src/warnings/warn-on-client-source-maps.ts +96 -0
  95. package/src/yuku.ts +67 -0
  96. package/dist/906.js +0 -1
  97. package/dist/946.js +0 -1
  98. package/dist/babel.d.ts +0 -8
  99. package/dist/rslib-runtime.js +0 -23
@@ -0,0 +1,207 @@
1
+ import { isAbsolute, relative } from 'node:path';
2
+ import type { RsbuildDevServer, Rspack } from '@rsbuild/core';
3
+ import type { ServerBuild } from 'react-router';
4
+ import type { ReactRouterManifestForDev } from './manifest.js';
5
+ import { resolveServerBuildModule } from './server-utils.js';
6
+
7
+ export type ReactRouterDevManifest = ReactRouterManifestForDev;
8
+
9
+ export type ReactRouterDevBuildPlan = {
10
+ defaultEntryName: string;
11
+ entryNames: readonly string[];
12
+ };
13
+
14
+ export type ReactRouterDevManifestSet = Readonly<
15
+ Record<string, ReactRouterDevManifest>
16
+ >;
17
+
18
+ export type ReactRouterServerBuilds = Readonly<Record<string, ServerBuild>>;
19
+
20
+ export type DependencySnapshot = {
21
+ files: ReadonlySet<string>;
22
+ contexts: ReadonlySet<string>;
23
+ missing: ReadonlySet<string>;
24
+ };
25
+
26
+ export type DevChangedFiles = {
27
+ known: boolean;
28
+ files: ReadonlySet<string>;
29
+ };
30
+
31
+ export type DevGraphChanges = {
32
+ web: DevChangedFiles;
33
+ node: DevChangedFiles;
34
+ };
35
+
36
+ export type DevCompilationIdentity = symbol;
37
+
38
+ export type DevGraphIdentity = {
39
+ web: DevCompilationIdentity | undefined;
40
+ node: DevCompilationIdentity | undefined;
41
+ nodeWeb: DevCompilationIdentity | undefined;
42
+ };
43
+
44
+ export type WebArtifact = {
45
+ manifestsByEntryName: ReactRouterDevManifestSet;
46
+ dependencies: DependencySnapshot;
47
+ };
48
+
49
+ export const snapshotDevChangedFiles = (
50
+ compiler: Pick<Rspack.Compiler, 'modifiedFiles' | 'removedFiles'> | undefined
51
+ ): DevChangedFiles => {
52
+ if (!compiler) {
53
+ return { known: false, files: new Set() };
54
+ }
55
+ return {
56
+ known:
57
+ compiler.modifiedFiles !== undefined ||
58
+ compiler.removedFiles !== undefined,
59
+ files: new Set([
60
+ ...(compiler.modifiedFiles ?? []),
61
+ ...(compiler.removedFiles ?? []),
62
+ ]),
63
+ };
64
+ };
65
+
66
+ export const snapshotDependencies = (
67
+ compilation: Rspack.Compilation
68
+ ): DependencySnapshot => ({
69
+ files: new Set([
70
+ ...compilation.fileDependencies,
71
+ ...(compilation.buildDependencies ?? []),
72
+ ]),
73
+ contexts: new Set(compilation.contextDependencies),
74
+ missing: new Set(compilation.missingDependencies),
75
+ });
76
+
77
+ const isWithinDirectory = (directory: string, file: string): boolean => {
78
+ const relativePath = relative(directory, file);
79
+ return (
80
+ relativePath === '' ||
81
+ (!relativePath.startsWith('..') && !isAbsolute(relativePath))
82
+ );
83
+ };
84
+
85
+ export const isSafeOneSidedChange = (
86
+ changes: DevChangedFiles,
87
+ dependencies: DependencySnapshot
88
+ ): boolean => {
89
+ if (!changes.known || changes.files.size === 0) {
90
+ return false;
91
+ }
92
+ for (const file of changes.files) {
93
+ if (dependencies.files.has(file) || dependencies.missing.has(file)) {
94
+ return false;
95
+ }
96
+ for (const directory of dependencies.contexts) {
97
+ if (isWithinDirectory(directory, file)) {
98
+ return false;
99
+ }
100
+ }
101
+ }
102
+ return true;
103
+ };
104
+
105
+ export const getEnvironmentStats = (
106
+ stats: Rspack.Stats | Rspack.MultiStats,
107
+ name: 'web' | 'node'
108
+ ): Rspack.Stats | undefined => {
109
+ const children = Array.isArray((stats as Rspack.MultiStats).stats)
110
+ ? (stats as Rspack.MultiStats).stats
111
+ : [stats as Rspack.Stats];
112
+ return children.find(child => {
113
+ const compilation = child.compilation;
114
+ return compilation.name === name || compilation.compiler?.name === name;
115
+ });
116
+ };
117
+
118
+ const evaluateServerBuild = async (
119
+ server: RsbuildDevServer,
120
+ entryName: string
121
+ ): Promise<ServerBuild> => {
122
+ const loaded = await server.environments.node.loadBundle(entryName);
123
+ return resolveServerBuildModule(
124
+ loaded,
125
+ `Server entry ${JSON.stringify(entryName)}`
126
+ );
127
+ };
128
+
129
+ export const evaluateServerBuilds = async (
130
+ server: RsbuildDevServer,
131
+ entryNames: readonly string[]
132
+ ): Promise<ReactRouterServerBuilds> => {
133
+ const evaluated = await Promise.all(
134
+ entryNames.map(async entryName => [
135
+ entryName,
136
+ await evaluateServerBuild(server, entryName),
137
+ ])
138
+ );
139
+ return Object.fromEntries(evaluated) as Record<string, ServerBuild>;
140
+ };
141
+
142
+ const assertBuildMatchesManifest = (
143
+ entryName: string,
144
+ build: ServerBuild,
145
+ manifest: ReactRouterDevManifest
146
+ ): void => {
147
+ for (const [routeId, manifestRoute] of Object.entries(manifest.routes)) {
148
+ const routeModule = build.routes[routeId]?.module;
149
+ if (!routeModule) {
150
+ throw new Error(
151
+ `[rsbuild-plugin-react-router] Server build ${JSON.stringify(entryName)} route ${JSON.stringify(routeId)} is missing from the evaluated server build.`
152
+ );
153
+ }
154
+ if (
155
+ Boolean(manifestRoute.hasLoader) !==
156
+ (typeof routeModule.loader === 'function')
157
+ ) {
158
+ throw new Error(
159
+ `[rsbuild-plugin-react-router] Server build ${JSON.stringify(entryName)} route ${JSON.stringify(routeId)} loader export does not match its web manifest.`
160
+ );
161
+ }
162
+ if (
163
+ Boolean(manifestRoute.hasAction) !==
164
+ (typeof routeModule.action === 'function')
165
+ ) {
166
+ throw new Error(
167
+ `[rsbuild-plugin-react-router] Server build ${JSON.stringify(entryName)} route ${JSON.stringify(routeId)} action export does not match its web manifest.`
168
+ );
169
+ }
170
+ }
171
+ };
172
+
173
+ const pinBuildToManifest = (
174
+ entryName: string,
175
+ build: ServerBuild,
176
+ manifest: ReactRouterDevManifest
177
+ ): ServerBuild => {
178
+ assertBuildMatchesManifest(entryName, build, manifest);
179
+ return {
180
+ ...build,
181
+ assets: structuredClone(manifest) as ServerBuild['assets'],
182
+ };
183
+ };
184
+
185
+ export const pinServerBuildsToManifests = (
186
+ builds: ReactRouterServerBuilds,
187
+ entryNames: readonly string[],
188
+ manifestsByEntryName: ReactRouterDevManifestSet
189
+ ): ReactRouterServerBuilds => {
190
+ const pinned: Record<string, ServerBuild> = {};
191
+ for (const entryName of entryNames) {
192
+ const build = builds[entryName];
193
+ if (!build) {
194
+ throw new Error(
195
+ `[rsbuild-plugin-react-router] Expected server build ${JSON.stringify(entryName)} was not evaluated.`
196
+ );
197
+ }
198
+ const manifest = manifestsByEntryName[entryName];
199
+ if (!manifest) {
200
+ throw new Error(
201
+ `[rsbuild-plugin-react-router] Server build ${JSON.stringify(entryName)} has no matching web manifest.`
202
+ );
203
+ }
204
+ pinned[entryName] = pinBuildToManifest(entryName, build, manifest);
205
+ }
206
+ return pinned;
207
+ };
@@ -0,0 +1,92 @@
1
+ import type { Rspack } from '@rsbuild/core';
2
+ import type {
3
+ DevCompilationIdentity,
4
+ DevGraphChanges,
5
+ DevGraphIdentity,
6
+ } from './dev-runtime-artifacts.js';
7
+
8
+ export type DevCompilerPair = {
9
+ web: Rspack.Compiler;
10
+ node: Rspack.Compiler;
11
+ settledCompilations: WeakSet<Rspack.Compilation>;
12
+ pendingAttempt?: PendingDevCompilation;
13
+ latestCompletedWebIdentity?: DevCompilationIdentity;
14
+ latestWebStart?: CompilationStart;
15
+ latestNodeStart?: CompilationStart;
16
+ };
17
+
18
+ export type PendingDevCompilation = {
19
+ stats: Rspack.Stats | Rspack.MultiStats;
20
+ changes: DevGraphChanges;
21
+ identity: DevGraphIdentity;
22
+ webCompilation: Rspack.Compilation;
23
+ nodeCompilation: Rspack.Compilation;
24
+ };
25
+
26
+ export type CompilationStart =
27
+ | { status: 'pending' }
28
+ | { status: 'started'; identity: DevCompilationIdentity };
29
+
30
+ export const isLatestStartedCompilation = (
31
+ identity: DevCompilationIdentity | undefined,
32
+ start: CompilationStart | undefined
33
+ ): boolean =>
34
+ !identity || (start?.status === 'started' && start.identity === identity);
35
+
36
+ export const hasPendingCompilation = (pair: DevCompilerPair): boolean =>
37
+ pair.latestWebStart?.status === 'pending' ||
38
+ pair.latestNodeStart?.status === 'pending';
39
+
40
+ export type CompilationIdentityTracker = {
41
+ getCompilationIdentity(
42
+ compilation: Rspack.Compilation
43
+ ): DevCompilationIdentity;
44
+ getWebIdentityForNodeCompilation(
45
+ compilation: Rspack.Compilation
46
+ ): DevCompilationIdentity | undefined;
47
+ setWebIdentityForNodeCompilation(
48
+ compilation: Rspack.Compilation,
49
+ identity: DevCompilationIdentity
50
+ ): void;
51
+ };
52
+
53
+ export const createCompilationIdentityTracker =
54
+ (): CompilationIdentityTracker => {
55
+ const identityByCompilation = new WeakMap<
56
+ Rspack.Compilation,
57
+ DevCompilationIdentity
58
+ >();
59
+ const webIdentityByNodeCompilation = new WeakMap<
60
+ Rspack.Compilation,
61
+ DevCompilationIdentity
62
+ >();
63
+
64
+ return {
65
+ getCompilationIdentity(
66
+ compilation: Rspack.Compilation
67
+ ): DevCompilationIdentity {
68
+ const existing = identityByCompilation.get(compilation);
69
+ if (existing) {
70
+ return existing;
71
+ }
72
+ const identity = Symbol();
73
+ // Keep compact lineage tokens in committed state without retaining entire
74
+ // Rspack compilation graphs across failed rebuilds.
75
+ identityByCompilation.set(compilation, identity);
76
+ return identity;
77
+ },
78
+
79
+ getWebIdentityForNodeCompilation(
80
+ compilation: Rspack.Compilation
81
+ ): DevCompilationIdentity | undefined {
82
+ return webIdentityByNodeCompilation.get(compilation);
83
+ },
84
+
85
+ setWebIdentityForNodeCompilation(
86
+ compilation: Rspack.Compilation,
87
+ identity: DevCompilationIdentity
88
+ ): void {
89
+ webIdentityByNodeCompilation.set(compilation, identity);
90
+ },
91
+ };
92
+ };