@react-router/dev 8.4.0 → 8.5.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/CHANGELOG.md +42 -0
- package/dist/{build-CsJF5XUO.js → build-DjEus3HZ.js} +10 -4
- package/dist/cli/index.js +4 -4
- package/dist/{config-t89niiFv.d.ts → config-DP95WFpo.d.ts} +41 -10
- package/dist/config.d.ts +1 -1
- package/dist/config.js +1 -1
- package/dist/{dev-_GaivbeG.js → dev-LVfdDvQH.js} +2 -2
- package/dist/{routes-BFdkiVnp.js → routes-DAb9gz9-.js} +1 -1
- package/dist/routes.js +2 -2
- package/dist/{typegen-WywajSVn.js → typegen-CqlAVM2O.js} +15 -3
- package/dist/vite.js +274 -174
- package/package.json +6 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,47 @@
|
|
|
1
1
|
# `@react-router/dev`
|
|
2
2
|
|
|
3
|
+
## v8.5.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Use resolved Vite environment output directories when reading and writing build artifacts ([#15480](https://github.com/remix-run/react-router/pull/15480))
|
|
8
|
+
- Finalize server-bundle manifest paths after asynchronous Vite configuration hooks complete
|
|
9
|
+
- Preserve output-directory overrides applied when creating a Vite build environment
|
|
10
|
+
- Run prerendering after other Vite plugins finish their application build hooks ([#15481](https://github.com/remix-run/react-router/pull/15481))
|
|
11
|
+
- Close React Router's build resources when another plugin's application build hook fails during `react-router build`
|
|
12
|
+
- Updated dependencies:
|
|
13
|
+
- [`react-router@8.5.1`](https://github.com/remix-run/react-router/releases/tag/react-router@8.5.1)
|
|
14
|
+
- [`@react-router/node@8.5.1`](https://github.com/remix-run/react-router/releases/tag/@react-router/node@8.5.1)
|
|
15
|
+
- [`@react-router/serve@8.5.1`](https://github.com/remix-run/react-router/releases/tag/@react-router/serve@8.5.1)
|
|
16
|
+
|
|
17
|
+
## v8.5.0
|
|
18
|
+
|
|
19
|
+
### Patch Changes
|
|
20
|
+
|
|
21
|
+
- Fix critical CSS collection in dev registering server-only route imports as client dependencies, which triggered dependency re-optimization and full page reloads ([#15595](https://github.com/remix-run/react-router/pull/15595))
|
|
22
|
+
- Fix intermittent `Prerender: Request failed for ... connect ECONNREFUSED` errors during prerendering ([#15325](https://github.com/remix-run/react-router/pull/15325))
|
|
23
|
+
- Send requests to the address the Vite preview server bound to
|
|
24
|
+
- Avoid re-resolving `localhost` for each request, which could select a different address family (`127.0.0.1` vs `::1`)
|
|
25
|
+
|
|
26
|
+
### Unstable Changes
|
|
27
|
+
|
|
28
|
+
⚠️ _[Unstable features](https://reactrouter.com/community/api-development-strategy#unstable-flags) are not recommended for production use_
|
|
29
|
+
|
|
30
|
+
- Add `ssr: "unstable_api-only"` to retain a runtime server for loaders, actions, and route discovery while disabling production document rendering ([#15601](https://github.com/remix-run/react-router/pull/15601))
|
|
31
|
+
- Generate a root-only SPA shell when prerendering is disabled
|
|
32
|
+
- Support prerendered pages and data files alongside runtime loaders and actions, with a SPA fallback for non-prerendered paths
|
|
33
|
+
- Default API-only builds to lazy route discovery
|
|
34
|
+
- Reject API-only configuration in RSC Framework Mode
|
|
35
|
+
- Preserve server-only route exports in additional Vite server environments in both API-only and SSR modes
|
|
36
|
+
- Serve prerendered pages and the SPA fallback in Vite preview while retaining live data requests and route discovery
|
|
37
|
+
- Add the `future.unstable_customRouteDiscovery` flag to opt into application-controlled route discovery in conventional Framework Mode ([#15602](https://github.com/remix-run/react-router/pull/15602))
|
|
38
|
+
- Fix source maps for route modules in unstable RSC Framework Mode ([#15479](https://github.com/remix-run/react-router/pull/15479))
|
|
39
|
+
- Add `unstable_apiServerOrigin` to configure the origin for API-only loader, action, and route discovery requests ([#15601](https://github.com/remix-run/react-router/pull/15601))
|
|
40
|
+
- Updated dependencies:
|
|
41
|
+
- [`react-router@8.5.0`](https://github.com/remix-run/react-router/releases/tag/react-router@8.5.0)
|
|
42
|
+
- [`@react-router/node@8.5.0`](https://github.com/remix-run/react-router/releases/tag/@react-router/node@8.5.0)
|
|
43
|
+
- [`@react-router/serve@8.5.0`](https://github.com/remix-run/react-router/releases/tag/@react-router/serve@8.5.0)
|
|
44
|
+
|
|
3
45
|
## v8.4.0
|
|
4
46
|
|
|
5
47
|
### Patch Changes
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @react-router/dev v8.
|
|
2
|
+
* @react-router/dev v8.5.1
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -8,12 +8,12 @@
|
|
|
8
8
|
*
|
|
9
9
|
* @license MIT
|
|
10
10
|
*/
|
|
11
|
-
import { _ as getVite, v as preloadVite } from "./typegen-
|
|
11
|
+
import { _ as getVite, v as preloadVite } from "./typegen-CqlAVM2O.js";
|
|
12
12
|
//#region vite/build.ts
|
|
13
13
|
async function build(root, viteBuildOptions) {
|
|
14
14
|
await preloadVite();
|
|
15
15
|
let { assetsInlineLimit, clearScreen, config: configFile, emptyOutDir, force, logLevel, minify, mode, sourcemapClient, sourcemapServer } = viteBuildOptions;
|
|
16
|
-
|
|
16
|
+
let builder = await getVite().createBuilder({
|
|
17
17
|
root,
|
|
18
18
|
mode,
|
|
19
19
|
configFile,
|
|
@@ -35,7 +35,13 @@ async function build(root, viteBuildOptions) {
|
|
|
35
35
|
if (!config.plugins.find((plugin) => plugin.name === "react-router" || plugin.name === "react-router/rsc")) throw new Error("React Router Vite plugin not found in Vite config");
|
|
36
36
|
}
|
|
37
37
|
}]
|
|
38
|
-
})
|
|
38
|
+
});
|
|
39
|
+
try {
|
|
40
|
+
await builder.buildApp();
|
|
41
|
+
} finally {
|
|
42
|
+
let { __reactRouterBuildContext: buildContext } = builder.config;
|
|
43
|
+
await buildContext?.close();
|
|
44
|
+
}
|
|
39
45
|
}
|
|
40
46
|
//#endregion
|
|
41
47
|
export { build };
|
package/dist/cli/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* @react-router/dev v8.
|
|
3
|
+
* @react-router/dev v8.5.1
|
|
4
4
|
*
|
|
5
5
|
* Copyright (c) Remix Software Inc.
|
|
6
6
|
*
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
*
|
|
10
10
|
* @license MIT
|
|
11
11
|
*/
|
|
12
|
-
import { _ as getVite, l as hasNodeDependency, n as watch, t as run$1, u as loadConfig, v as preloadVite } from "../typegen-
|
|
12
|
+
import { _ as getVite, l as hasNodeDependency, n as watch, t as run$1, u as loadConfig, v as preloadVite } from "../typegen-CqlAVM2O.js";
|
|
13
13
|
import { createRequire } from "node:module";
|
|
14
14
|
import { parseArgs } from "node:util";
|
|
15
15
|
import semver from "semver";
|
|
@@ -172,7 +172,7 @@ async function routes(rootDirectory, flags = {}) {
|
|
|
172
172
|
}
|
|
173
173
|
async function build(root, options = {}) {
|
|
174
174
|
root = resolveRootDirectory(root, options);
|
|
175
|
-
let { build } = await import("../build-
|
|
175
|
+
let { build } = await import("../build-DjEus3HZ.js");
|
|
176
176
|
if (options.profile) await start();
|
|
177
177
|
try {
|
|
178
178
|
await build(root, options);
|
|
@@ -182,7 +182,7 @@ async function build(root, options = {}) {
|
|
|
182
182
|
}
|
|
183
183
|
async function dev(root, options = {}) {
|
|
184
184
|
if (developmentConditionEnabled) {
|
|
185
|
-
let { dev } = await import("../dev-
|
|
185
|
+
let { dev } = await import("../dev-LVfdDvQH.js");
|
|
186
186
|
if (options.profile) await start();
|
|
187
187
|
exitHook(() => stop(console.info));
|
|
188
188
|
root = resolveRootDirectory(root, options);
|
|
@@ -38,6 +38,7 @@ type ServerBundlesBuildManifest = BaseBuildManifest & {
|
|
|
38
38
|
};
|
|
39
39
|
type ServerModuleFormat = "esm" | "cjs";
|
|
40
40
|
interface FutureConfig {
|
|
41
|
+
unstable_customRouteDiscovery: boolean;
|
|
41
42
|
unstable_enableNodeReadableStream: boolean;
|
|
42
43
|
unstable_optimizeDeps: boolean;
|
|
43
44
|
}
|
|
@@ -140,12 +141,30 @@ type ReactRouterConfig = {
|
|
|
140
141
|
*/
|
|
141
142
|
serverBundles?: ServerBundlesFunction;
|
|
142
143
|
/**
|
|
143
|
-
*
|
|
144
|
-
*
|
|
145
|
-
* `
|
|
146
|
-
*
|
|
144
|
+
* Control runtime server-side document rendering. Defaults to `true`.
|
|
145
|
+
*
|
|
146
|
+
* Set `false` to generate a static client build without a runtime server.
|
|
147
|
+
* Without prerendering, this generates a root-only SPA shell. With
|
|
148
|
+
* prerendering, it generates HTML and data files for selected paths plus
|
|
149
|
+
* a SPA fallback for non-prerendered paths.
|
|
150
|
+
*
|
|
151
|
+
* Set `"unstable_api-only"` to retain a runtime server for loaders, actions,
|
|
152
|
+
* and route discovery while disabling production document rendering.
|
|
153
|
+
* Documents follow the same prerendering and SPA fallback behavior as
|
|
154
|
+
* `ssr:false`, with runtime loaders and actions available for all routes.
|
|
155
|
+
* API-only mode is unstable and is not supported in RSC Framework Mode.
|
|
156
|
+
*/
|
|
157
|
+
ssr?: boolean | "unstable_api-only";
|
|
158
|
+
/**
|
|
159
|
+
* The origin to use for server requests when `ssr` is `"unstable_api-only"`.
|
|
160
|
+
* This is ignored when `ssr` is `true` or `false`. Defaults to the same
|
|
161
|
+
* origin that serves the client build. Applies to loader, action, and route
|
|
162
|
+
* discovery requests.
|
|
163
|
+
*
|
|
164
|
+
* **Note:** The server origin will need to be configured appropriately for
|
|
165
|
+
* Cross-Origin Request Sharing (CORS).
|
|
147
166
|
*/
|
|
148
|
-
|
|
167
|
+
unstable_apiServerOrigin?: string;
|
|
149
168
|
/**
|
|
150
169
|
* Enable subresource integrity hashes on asset script tags. Defaults to
|
|
151
170
|
* `false`.
|
|
@@ -256,12 +275,24 @@ type ResolvedReactRouterConfig = Readonly<{
|
|
|
256
275
|
*/
|
|
257
276
|
serverModuleFormat: ServerModuleFormat;
|
|
258
277
|
/**
|
|
259
|
-
*
|
|
260
|
-
*
|
|
261
|
-
* `
|
|
262
|
-
*
|
|
278
|
+
* Control runtime server-side document rendering. Defaults to `true`.
|
|
279
|
+
*
|
|
280
|
+
* Set `false` to generate a static client build without a runtime server.
|
|
281
|
+
* Without prerendering, this generates a root-only SPA shell. With
|
|
282
|
+
* prerendering, it generates HTML and data files for selected paths plus
|
|
283
|
+
* a SPA fallback for non-prerendered paths.
|
|
284
|
+
*
|
|
285
|
+
* Set `"unstable_api-only"` to retain a runtime server for loaders, actions,
|
|
286
|
+
* and route discovery while disabling production document rendering.
|
|
287
|
+
* Documents follow the same prerendering and SPA fallback behavior as
|
|
288
|
+
* `ssr:false`, with runtime loaders and actions available for all routes.
|
|
289
|
+
* API-only mode is unstable and is not supported in RSC Framework Mode.
|
|
290
|
+
*/
|
|
291
|
+
ssr: boolean | "unstable_api-only";
|
|
292
|
+
/**
|
|
293
|
+
* The origin to use for server requests in API-only mode.
|
|
263
294
|
*/
|
|
264
|
-
|
|
295
|
+
unstable_apiServerOrigin?: string;
|
|
265
296
|
/**
|
|
266
297
|
* Whether to generate subresource integrity hashes for asset script tags.
|
|
267
298
|
*/
|
package/dist/config.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
|
|
2
|
-
import { i as ServerBundlesFunction, n as Preset, r as ReactRouterConfig, t as BuildManifest } from "./config-
|
|
2
|
+
import { i as ServerBundlesFunction, n as Preset, r as ReactRouterConfig, t as BuildManifest } from "./config-DP95WFpo.js";
|
|
3
3
|
export type { BuildManifest, ReactRouterConfig as Config, Preset, ServerBundlesFunction };
|
package/dist/config.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @react-router/dev v8.
|
|
2
|
+
* @react-router/dev v8.5.1
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*
|
|
9
9
|
* @license MIT
|
|
10
10
|
*/
|
|
11
|
-
import { _ as getVite, v as preloadVite } from "./typegen-
|
|
11
|
+
import { _ as getVite, v as preloadVite } from "./typegen-CqlAVM2O.js";
|
|
12
12
|
import { n as start, r as stop, t as getSession } from "./cli/index.js";
|
|
13
13
|
import colors from "picocolors";
|
|
14
14
|
//#region vite/dev.ts
|
package/dist/routes.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @react-router/dev v8.
|
|
2
|
+
* @react-router/dev v8.5.1
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -8,5 +8,5 @@
|
|
|
8
8
|
*
|
|
9
9
|
* @license MIT
|
|
10
10
|
*/
|
|
11
|
-
import { a as prefix, i as layout, n as getAppDirectory, o as relative, r as index, s as route } from "./routes-
|
|
11
|
+
import { a as prefix, i as layout, n as getAppDirectory, o as relative, r as index, s as route } from "./routes-DAb9gz9-.js";
|
|
12
12
|
export { getAppDirectory, index, layout, prefix, relative, route };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @react-router/dev v8.
|
|
2
|
+
* @react-router/dev v8.5.1
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*
|
|
9
9
|
* @license MIT
|
|
10
10
|
*/
|
|
11
|
-
import { c as setAppDirectory, l as validateRouteConfig, t as configRoutesToRouteManifest, u as invariant } from "./routes-
|
|
11
|
+
import { c as setAppDirectory, l as validateRouteConfig, t as configRoutesToRouteManifest, u as invariant } from "./routes-DAb9gz9-.js";
|
|
12
12
|
import { createRequire } from "node:module";
|
|
13
13
|
import colors from "picocolors";
|
|
14
14
|
import fs from "node:fs";
|
|
@@ -228,10 +228,18 @@ async function resolveConfig({ root, viteRunnerContext, reactRouterConfigFile, s
|
|
|
228
228
|
ssr: true
|
|
229
229
|
};
|
|
230
230
|
let userAndPresetConfigs = mergeReactRouterConfig(...presets, reactRouterUserConfig);
|
|
231
|
-
let { appDirectory: userAppDirectory, basename, buildDirectory: userBuildDirectory, buildEnd, prerender, routeDiscovery: userRouteDiscovery, serverBuildFile, serverBundles, serverModuleFormat, ssr } = {
|
|
231
|
+
let { appDirectory: userAppDirectory, basename, buildDirectory: userBuildDirectory, buildEnd, prerender, routeDiscovery: userRouteDiscovery, serverBuildFile, serverBundles, serverModuleFormat, ssr, unstable_apiServerOrigin } = {
|
|
232
232
|
...defaults,
|
|
233
233
|
...userAndPresetConfigs
|
|
234
234
|
};
|
|
235
|
+
if (ssr === "unstable_api-only" && unstable_apiServerOrigin != null) try {
|
|
236
|
+
let url = new URL(unstable_apiServerOrigin);
|
|
237
|
+
if (url.pathname !== "/" || url.search || url.hash) return err("The `unstable_apiServerOrigin` config must be an origin without a path, query, or hash.");
|
|
238
|
+
unstable_apiServerOrigin = url.origin;
|
|
239
|
+
} catch {
|
|
240
|
+
return err("The `unstable_apiServerOrigin` config must be a valid absolute URL.");
|
|
241
|
+
}
|
|
242
|
+
else unstable_apiServerOrigin = void 0;
|
|
235
243
|
if (!ssr && serverBundles) serverBundles = void 0;
|
|
236
244
|
if (prerender) {
|
|
237
245
|
let isValidPrerenderPathsConfig = (p) => typeof p === "boolean" || typeof p === "function" || Array.isArray(p);
|
|
@@ -295,6 +303,7 @@ async function resolveConfig({ root, viteRunnerContext, reactRouterConfigFile, s
|
|
|
295
303
|
if ("unstable_subResourceIntegrity" in futureConfig) return err("The `future.unstable_subResourceIntegrity` flag has been stabilized and moved to a top-level `config.subResourceIntegrity` field");
|
|
296
304
|
}
|
|
297
305
|
let future = {
|
|
306
|
+
unstable_customRouteDiscovery: userAndPresetConfigs.future?.unstable_customRouteDiscovery ?? false,
|
|
298
307
|
unstable_enableNodeReadableStream: userAndPresetConfigs.future?.unstable_enableNodeReadableStream ?? false,
|
|
299
308
|
unstable_optimizeDeps: userAndPresetConfigs.future?.unstable_optimizeDeps ?? false
|
|
300
309
|
};
|
|
@@ -314,6 +323,7 @@ async function resolveConfig({ root, viteRunnerContext, reactRouterConfigFile, s
|
|
|
314
323
|
serverBundles,
|
|
315
324
|
serverModuleFormat,
|
|
316
325
|
ssr,
|
|
326
|
+
unstable_apiServerOrigin,
|
|
317
327
|
splitRouteModules,
|
|
318
328
|
subResourceIntegrity,
|
|
319
329
|
allowedActionOrigins,
|
|
@@ -624,6 +634,8 @@ function generateServerBuild(ctx) {
|
|
|
624
634
|
export const routeDiscovery: ServerBuild["routeDiscovery"];
|
|
625
635
|
export const routes: ServerBuild["routes"];
|
|
626
636
|
export const ssr: ServerBuild["ssr"];
|
|
637
|
+
export const unstable_apiOnly: ServerBuild["unstable_apiOnly"];
|
|
638
|
+
export const unstable_apiServerOrigin: ServerBuild["unstable_apiServerOrigin"];
|
|
627
639
|
export const allowedActionOrigins: ServerBuild["allowedActionOrigins"];
|
|
628
640
|
export const unstable_getCriticalCss: ServerBuild["unstable_getCriticalCss"];
|
|
629
641
|
}
|
package/dist/vite.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @react-router/dev v8.
|
|
2
|
+
* @react-router/dev v8.5.1
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
*
|
|
9
9
|
* @license MIT
|
|
10
10
|
*/
|
|
11
|
-
import { _ as getVite, a as t, c as createConfigLoader, d as resolveEntryFiles, f as resolveRSCEntryFiles, g as getUserBuildRollupOptions, h as defineOptimizeDepsCompilerOptions, i as parse$1, l as hasNodeDependency, m as defineCompilerOptions, n as watch, o as traverse, p as ssrExternals, r as generate, s as configRouteToBranchRoute, v as preloadVite } from "./typegen-
|
|
12
|
-
import { u as invariant } from "./routes-
|
|
11
|
+
import { _ as getVite, a as t, c as createConfigLoader, d as resolveEntryFiles, f as resolveRSCEntryFiles, g as getUserBuildRollupOptions, h as defineOptimizeDepsCompilerOptions, i as parse$1, l as hasNodeDependency, m as defineCompilerOptions, n as watch, o as traverse, p as ssrExternals, r as generate, s as configRouteToBranchRoute, v as preloadVite } from "./typegen-CqlAVM2O.js";
|
|
12
|
+
import { u as invariant } from "./routes-DAb9gz9-.js";
|
|
13
13
|
import { createRequire } from "node:module";
|
|
14
14
|
import colors from "picocolors";
|
|
15
15
|
import { existsSync, readFileSync, readdirSync } from "node:fs";
|
|
@@ -114,7 +114,8 @@ const findDeps = async (vite, node, deps) => {
|
|
|
114
114
|
}
|
|
115
115
|
}
|
|
116
116
|
async function addFromUrl(url) {
|
|
117
|
-
let
|
|
117
|
+
let ssrNode = await vite.environments.ssr.moduleGraph.getModuleByUrl(url);
|
|
118
|
+
let node = ssrNode?.id ? vite.moduleGraph.getModuleById(ssrNode.id) : void 0;
|
|
118
119
|
if (node) await addFromNode(node);
|
|
119
120
|
}
|
|
120
121
|
if (node.ssrTransformResult) {
|
|
@@ -788,90 +789,91 @@ function normalizePostProcessResult(result) {
|
|
|
788
789
|
* Vite plugin for prerendering using the preview server
|
|
789
790
|
*/
|
|
790
791
|
function prerender(options) {
|
|
791
|
-
const { config, requests, postProcess = defaultPostProcess, handleError = defaultHandleError, logFile, finalize } = options;
|
|
792
|
+
const { config, requests, postProcess = defaultPostProcess, handleError = defaultHandleError, logFile, finalize, cleanup } = options;
|
|
792
793
|
let viteConfig;
|
|
793
794
|
return {
|
|
794
795
|
name: "prerender",
|
|
796
|
+
enforce: "post",
|
|
795
797
|
sharedDuringBuild: true,
|
|
796
|
-
|
|
798
|
+
buildApp: {
|
|
797
799
|
order: "post",
|
|
798
|
-
handler(
|
|
799
|
-
|
|
800
|
-
|
|
800
|
+
async handler() {
|
|
801
|
+
let ogIsBuildRequest = process.env.IS_RR_BUILD_REQUEST;
|
|
802
|
+
try {
|
|
801
803
|
const prerenderRequests = (typeof requests === "function" ? await requests() : requests).map(normalizePrerenderRequest);
|
|
802
804
|
if (prerenderRequests.length === 0) return;
|
|
803
|
-
const { buildDirectory = viteConfig.environments.client.build.outDir, concurrency = 1, retryCount = 0, retryDelay = 500, maxRedirects = 0, timeout = 1e4 } = (typeof config === "function" ? await config() : config) ?? {};
|
|
804
|
-
let ogIsBuildRequest = process.env.IS_RR_BUILD_REQUEST;
|
|
805
|
+
const { buildDirectory = path.resolve(viteConfig.root, viteConfig.environments.client.build.outDir), concurrency = 1, retryCount = 0, retryDelay = 500, maxRedirects = 0, timeout = 1e4 } = (typeof config === "function" ? await config() : config) ?? {};
|
|
805
806
|
process.env.IS_RR_BUILD_REQUEST = "yes";
|
|
807
|
+
const previewServer = await startPreviewServer(viteConfig);
|
|
806
808
|
try {
|
|
807
|
-
const
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
url.protocol = baseUrl.protocol;
|
|
818
|
-
url.port = baseUrl.port;
|
|
819
|
-
}
|
|
820
|
-
async function attempt(url) {
|
|
821
|
-
try {
|
|
822
|
-
const signal = AbortSignal.timeout(timeout);
|
|
823
|
-
const response = await nodeHttpFetch(new Request(url, request), { signal });
|
|
824
|
-
if (response.status >= 300 && response.status < 400 && response.headers.has("location") && ++redirectCount <= maxRedirects) {
|
|
825
|
-
const location = response.headers.get("location");
|
|
826
|
-
const responseURL = new URL(response.url);
|
|
827
|
-
const locationUrl = new URL(location, response.url);
|
|
828
|
-
if (responseURL.origin !== locationUrl.origin) return await postProcess(request, response, metadata);
|
|
829
|
-
return await attempt(new URL(location, url));
|
|
830
|
-
}
|
|
831
|
-
if (response.status >= 500 && ++attemptCount <= retryCount) {
|
|
832
|
-
await new Promise((resolve) => setTimeout(resolve, retryDelay));
|
|
833
|
-
return attempt(url);
|
|
834
|
-
}
|
|
835
|
-
return await postProcess(request, response, metadata);
|
|
836
|
-
} catch (error) {
|
|
837
|
-
if (++attemptCount <= retryCount) {
|
|
838
|
-
await new Promise((resolve) => setTimeout(resolve, retryDelay));
|
|
839
|
-
return attempt(url);
|
|
840
|
-
}
|
|
841
|
-
handleError(request, error instanceof Error ? error : new Error(error?.toString() ?? "Unknown error"), metadata);
|
|
842
|
-
return [];
|
|
843
|
-
}
|
|
844
|
-
}
|
|
845
|
-
return attempt(url);
|
|
809
|
+
const baseUrl = getResolvedUrl(previewServer);
|
|
810
|
+
async function prerenderRequest(input, metadata) {
|
|
811
|
+
let attemptCount = 0;
|
|
812
|
+
let redirectCount = 0;
|
|
813
|
+
const request = new Request(input);
|
|
814
|
+
const url = new URL(request.url);
|
|
815
|
+
if (url.origin !== baseUrl.origin) {
|
|
816
|
+
url.hostname = baseUrl.hostname;
|
|
817
|
+
url.protocol = baseUrl.protocol;
|
|
818
|
+
url.port = baseUrl.port;
|
|
846
819
|
}
|
|
847
|
-
async function
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
820
|
+
async function attempt(url) {
|
|
821
|
+
try {
|
|
822
|
+
const signal = AbortSignal.timeout(timeout);
|
|
823
|
+
const response = await nodeHttpFetch(new Request(url, request), { signal });
|
|
824
|
+
if (response.status >= 300 && response.status < 400 && response.headers.has("location") && ++redirectCount <= maxRedirects) {
|
|
825
|
+
const location = response.headers.get("location");
|
|
826
|
+
const responseURL = new URL(response.url);
|
|
827
|
+
const locationUrl = new URL(location, response.url);
|
|
828
|
+
if (responseURL.origin !== locationUrl.origin) return await postProcess(request, response, metadata);
|
|
829
|
+
return await attempt(new URL(location, url));
|
|
830
|
+
}
|
|
831
|
+
if (response.status >= 500 && ++attemptCount <= retryCount) {
|
|
832
|
+
await new Promise((resolve) => setTimeout(resolve, retryDelay));
|
|
833
|
+
return attempt(url);
|
|
834
|
+
}
|
|
835
|
+
return await postProcess(request, response, metadata);
|
|
836
|
+
} catch (error) {
|
|
837
|
+
if (++attemptCount <= retryCount) {
|
|
838
|
+
await new Promise((resolve) => setTimeout(resolve, retryDelay));
|
|
839
|
+
return attempt(url);
|
|
840
|
+
}
|
|
841
|
+
handleError(request, error instanceof Error ? error : new Error(error?.toString() ?? "Unknown error"), metadata);
|
|
842
|
+
return [];
|
|
853
843
|
}
|
|
854
844
|
}
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
845
|
+
return attempt(url);
|
|
846
|
+
}
|
|
847
|
+
async function prerender(input, metadata) {
|
|
848
|
+
const { files, requests } = normalizePostProcessResult(await prerenderRequest(input, metadata));
|
|
849
|
+
for (const file of files) await writePrerenderFile(file, metadata);
|
|
850
|
+
for (const followUp of requests) {
|
|
851
|
+
const normalized = normalizePrerenderRequest(followUp);
|
|
852
|
+
await prerender(normalized.request, normalized.metadata);
|
|
863
853
|
}
|
|
864
|
-
await (await import("p-map")).default(prerenderRequests, async ({ request, metadata }) => {
|
|
865
|
-
await prerender(request, metadata);
|
|
866
|
-
}, { concurrency });
|
|
867
|
-
if (finalize) await finalize(buildDirectory);
|
|
868
|
-
} finally {
|
|
869
|
-
await previewServer.close();
|
|
870
854
|
}
|
|
855
|
+
async function writePrerenderFile(file, metadata) {
|
|
856
|
+
const normalizedPath = file.path.startsWith("/") ? file.path.slice(1) : file.path;
|
|
857
|
+
const outputPath = path.join(buildDirectory, ...normalizedPath.split("/"));
|
|
858
|
+
await mkdir(path.dirname(outputPath), { recursive: true });
|
|
859
|
+
await writeFile(outputPath, file.contents);
|
|
860
|
+
const relativePath = path.relative(viteConfig.root, outputPath);
|
|
861
|
+
if (logFile) logFile(relativePath, metadata);
|
|
862
|
+
return relativePath;
|
|
863
|
+
}
|
|
864
|
+
await (await import("p-map")).default(prerenderRequests, async ({ request, metadata }) => {
|
|
865
|
+
await prerender(request, metadata);
|
|
866
|
+
}, { concurrency });
|
|
867
|
+
if (finalize) await finalize(buildDirectory);
|
|
871
868
|
} finally {
|
|
872
|
-
|
|
869
|
+
await previewServer.close();
|
|
873
870
|
}
|
|
874
|
-
}
|
|
871
|
+
} catch (error) {
|
|
872
|
+
await cleanup?.();
|
|
873
|
+
throw error;
|
|
874
|
+
} finally {
|
|
875
|
+
process.env.IS_RR_BUILD_REQUEST = ogIsBuildRequest;
|
|
876
|
+
}
|
|
875
877
|
}
|
|
876
878
|
},
|
|
877
879
|
configResolved(resolvedConfig) {
|
|
@@ -916,7 +918,7 @@ async function nodeHttpFetch(request, { signal }) {
|
|
|
916
918
|
return new Promise((resolve, reject) => {
|
|
917
919
|
const req = http.request({
|
|
918
920
|
protocol: url.protocol,
|
|
919
|
-
hostname: url.hostname,
|
|
921
|
+
hostname: url.hostname.replace(/^\[|\]$/g, ""),
|
|
920
922
|
port: url.port || void 0,
|
|
921
923
|
path: url.pathname + url.search,
|
|
922
924
|
method: request.method,
|
|
@@ -966,9 +968,15 @@ async function startPreviewServer(viteConfig) {
|
|
|
966
968
|
}
|
|
967
969
|
}
|
|
968
970
|
function getResolvedUrl(previewServer) {
|
|
969
|
-
const
|
|
970
|
-
|
|
971
|
-
|
|
971
|
+
const printableUrl = previewServer.resolvedUrls?.local[0];
|
|
972
|
+
const address = previewServer.httpServer?.address();
|
|
973
|
+
if (address && typeof address === "object" && address.address !== "::" && address.address !== "0.0.0.0") {
|
|
974
|
+
const protocol = printableUrl ? new URL(printableUrl).protocol : "http:";
|
|
975
|
+
const hostname = address.family === "IPv6" ? `[${address.address}]` : address.address;
|
|
976
|
+
return new URL(`${protocol}//${hostname}:${address.port}/`);
|
|
977
|
+
}
|
|
978
|
+
if (!printableUrl) throw new Error("Prerender: No resolved URL is available from the Vite preview server");
|
|
979
|
+
return new URL(printableUrl);
|
|
972
980
|
}
|
|
973
981
|
//#endregion
|
|
974
982
|
//#region vite/plugin.ts
|
|
@@ -1151,8 +1159,14 @@ const getRouteModuleExports = async (viteChildCompiler, ctx, routeFile, readRout
|
|
|
1151
1159
|
if (!viteChildCompiler) throw new Error("Vite child compiler not found");
|
|
1152
1160
|
return getExportNames(await compileRouteFile(viteChildCompiler, ctx, routeFile, readRouteFile));
|
|
1153
1161
|
};
|
|
1154
|
-
let
|
|
1155
|
-
let
|
|
1162
|
+
let getDefaultServerBuildDirectory = (reactRouterConfig, { serverBundleId } = {}) => path$2.join(reactRouterConfig.buildDirectory, "server", ...serverBundleId ? [serverBundleId] : []);
|
|
1163
|
+
let getDefaultClientBuildDirectory = (reactRouterConfig) => path$2.join(reactRouterConfig.buildDirectory, "client");
|
|
1164
|
+
let getClientBuildDirectory$1 = (viteConfig) => path$2.resolve(viteConfig.root, viteConfig.environments.client.build.outDir);
|
|
1165
|
+
let getServerBuildDirectory = (viteConfig, environmentName = "ssr") => {
|
|
1166
|
+
let environment = viteConfig.environments[environmentName];
|
|
1167
|
+
invariant(environment, `Vite environment "${environmentName}" not found`);
|
|
1168
|
+
return path$2.resolve(viteConfig.root, environment.build.outDir);
|
|
1169
|
+
};
|
|
1156
1170
|
let getServerBundleRouteIds = (vitePluginContext, ctx) => {
|
|
1157
1171
|
if (!ctx.buildManifest) return;
|
|
1158
1172
|
let environmentName = vitePluginContext.environment.name;
|
|
@@ -1182,9 +1196,12 @@ const reactRouterVitePlugin = () => {
|
|
|
1182
1196
|
let logger;
|
|
1183
1197
|
let firstLoad = true;
|
|
1184
1198
|
let ctx;
|
|
1185
|
-
let
|
|
1199
|
+
let closeChildCompiler = async () => {
|
|
1186
1200
|
await viteChildCompiler?.close();
|
|
1187
1201
|
viteChildCompiler = null;
|
|
1202
|
+
};
|
|
1203
|
+
let closePluginResources = async () => {
|
|
1204
|
+
await closeChildCompiler();
|
|
1188
1205
|
await reactRouterConfigLoader.close();
|
|
1189
1206
|
await (await typegenWatcherPromise)?.close();
|
|
1190
1207
|
typegenWatcherPromise = void 0;
|
|
@@ -1226,6 +1243,12 @@ const reactRouterVitePlugin = () => {
|
|
|
1226
1243
|
buildManifest
|
|
1227
1244
|
};
|
|
1228
1245
|
};
|
|
1246
|
+
let updateServerBundlePaths = () => {
|
|
1247
|
+
if (!ctx.buildManifest?.serverBundles) return;
|
|
1248
|
+
invariant(viteConfig);
|
|
1249
|
+
let { normalizePath } = getVite();
|
|
1250
|
+
for (let bundle of Object.values(ctx.buildManifest.serverBundles)) bundle.file = normalizePath(path$2.join(path$2.relative(ctx.rootDirectory, getServerBuildDirectory(viteConfig, `${SSR_BUNDLE_PREFIX}${bundle.id}`)), ctx.reactRouterConfig.serverBuildFile));
|
|
1251
|
+
};
|
|
1229
1252
|
let getServerEntry = async ({ routeIds }) => {
|
|
1230
1253
|
invariant(viteConfig, "viteconfig required to generate the server entry");
|
|
1231
1254
|
let routes = routeIds ? pick(ctx.reactRouterConfig.routes, routeIds) : ctx.reactRouterConfig.routes;
|
|
@@ -1237,14 +1260,16 @@ const reactRouterVitePlugin = () => {
|
|
|
1237
1260
|
import * as entryServer from ${JSON.stringify(resolveFileUrl(ctx, ctx.entryServerFilePath, { publicPath: ctx.publicPath }))};
|
|
1238
1261
|
${Object.keys(routes).map((key, index) => {
|
|
1239
1262
|
let route = routes[key];
|
|
1240
|
-
if (isSpaMode && key !== "root") return `const route${index} = { default: () => null };`;
|
|
1263
|
+
if (isSpaMode && !isApiOnlyMode(ctx.reactRouterConfig) && key !== "root") return `const route${index} = { default: () => null };`;
|
|
1241
1264
|
else return `import * as route${index} from ${JSON.stringify(resolveFileUrl(ctx, resolveRelativeRouteFilePath(route, ctx.reactRouterConfig), { publicPath: ctx.publicPath }))};`;
|
|
1242
1265
|
}).join("\n")}
|
|
1243
1266
|
export { default as assets } from ${JSON.stringify(virtual$1.serverManifest.id)};
|
|
1244
|
-
export const assetsBuildDirectory = ${JSON.stringify(path$2.relative(ctx.rootDirectory, getClientBuildDirectory$1(
|
|
1267
|
+
export const assetsBuildDirectory = ${JSON.stringify(path$2.relative(ctx.rootDirectory, getClientBuildDirectory$1(viteConfig)))};
|
|
1245
1268
|
export const basename = ${JSON.stringify(ctx.reactRouterConfig.basename)};
|
|
1246
1269
|
export const future = ${JSON.stringify(ctx.reactRouterConfig.future)};
|
|
1247
|
-
export const ssr = ${ctx.reactRouterConfig.ssr};
|
|
1270
|
+
export const ssr = ${Boolean(ctx.reactRouterConfig.ssr)};
|
|
1271
|
+
export const unstable_apiOnly = ${isApiOnlyMode(ctx.reactRouterConfig)};
|
|
1272
|
+
export const unstable_apiServerOrigin = ${isApiOnlyMode(ctx.reactRouterConfig) ? JSON.stringify(ctx.reactRouterConfig.unstable_apiServerOrigin) : "undefined"};
|
|
1248
1273
|
export const isSpaMode = ${isSpaMode};
|
|
1249
1274
|
export const prerender = ${JSON.stringify(prerenderPaths)};
|
|
1250
1275
|
export const routeDiscovery = ${JSON.stringify(ctx.reactRouterConfig.routeDiscovery)};
|
|
@@ -1283,8 +1308,8 @@ const reactRouterVitePlugin = () => {
|
|
|
1283
1308
|
let chunkAssetPaths = Object.values(viteManifest).flatMap((chunk) => chunk.assets ?? []);
|
|
1284
1309
|
return new Set([...cssUrlPaths, ...chunkAssetPaths]);
|
|
1285
1310
|
};
|
|
1286
|
-
let generateSriManifest = async (ctx) => {
|
|
1287
|
-
let clientBuildDirectory = getClientBuildDirectory$1(
|
|
1311
|
+
let generateSriManifest = async (ctx, viteConfig) => {
|
|
1312
|
+
let clientBuildDirectory = getClientBuildDirectory$1(viteConfig);
|
|
1288
1313
|
let entries = readdirSync(clientBuildDirectory, {
|
|
1289
1314
|
withFileTypes: true,
|
|
1290
1315
|
recursive: true
|
|
@@ -1307,7 +1332,7 @@ const reactRouterVitePlugin = () => {
|
|
|
1307
1332
|
};
|
|
1308
1333
|
let generateReactRouterManifestsForBuild = async ({ viteConfig, routeIds }) => {
|
|
1309
1334
|
invariant(viteConfig);
|
|
1310
|
-
let viteManifest = await loadViteManifest(getClientBuildDirectory$1(
|
|
1335
|
+
let viteManifest = await loadViteManifest(getClientBuildDirectory$1(viteConfig));
|
|
1311
1336
|
let allDynamicCssFiles = getAllDynamicCssFiles(ctx, viteManifest);
|
|
1312
1337
|
let entry = getReactRouterManifestBuildAssets(ctx, viteConfig, viteManifest, allDynamicCssFiles, ctx.entryClientFilePath, null);
|
|
1313
1338
|
let browserRoutes = {};
|
|
@@ -1372,9 +1397,9 @@ const reactRouterVitePlugin = () => {
|
|
|
1372
1397
|
...nonFingerprintedValues,
|
|
1373
1398
|
sri: void 0
|
|
1374
1399
|
};
|
|
1375
|
-
await writeFileSafe(path$2.join(getClientBuildDirectory$1(
|
|
1400
|
+
await writeFileSafe(path$2.join(getClientBuildDirectory$1(viteConfig), manifestPath), `window.__reactRouterManifest=${JSON.stringify(reactRouterBrowserManifest)};`);
|
|
1376
1401
|
let sri = void 0;
|
|
1377
|
-
if (ctx.reactRouterConfig.subResourceIntegrity) sri = await generateSriManifest(ctx);
|
|
1402
|
+
if (ctx.reactRouterConfig.subResourceIntegrity) sri = await generateSriManifest(ctx, viteConfig);
|
|
1378
1403
|
return {
|
|
1379
1404
|
reactRouterBrowserManifest,
|
|
1380
1405
|
reactRouterServerManifest: {
|
|
@@ -1485,12 +1510,17 @@ const reactRouterVitePlugin = () => {
|
|
|
1485
1510
|
watch: viteCommand === "serve"
|
|
1486
1511
|
});
|
|
1487
1512
|
await updatePluginContext();
|
|
1513
|
+
if (_viteConfigEnv.isPreview && ctx.reactRouterConfig.serverBundles) ctx.buildManifest = await getBuildManifest({
|
|
1514
|
+
reactRouterConfig: ctx.reactRouterConfig,
|
|
1515
|
+
rootDirectory: ctx.rootDirectory
|
|
1516
|
+
});
|
|
1488
1517
|
let environments = await getEnvironmentsOptions(ctx, viteCommand, { viteUserConfig });
|
|
1489
1518
|
let serverEnvironment = getServerEnvironmentValues(ctx, environments)[0];
|
|
1490
1519
|
invariant(serverEnvironment);
|
|
1491
1520
|
return {
|
|
1492
1521
|
__reactRouterPluginContext: ctx,
|
|
1493
|
-
|
|
1522
|
+
__reactRouterBuildContext: { close: closePluginResources },
|
|
1523
|
+
appType: viteCommand === "serve" && _viteConfigEnv.mode === "production" && (!ctx.reactRouterConfig.ssr || ctx.reactRouterConfig.ssr === "unstable_api-only") ? isApiOnlyMode(ctx.reactRouterConfig) ? "mpa" : "spa" : "custom",
|
|
1494
1524
|
ssr: {
|
|
1495
1525
|
external: serverEnvironment.resolve?.external,
|
|
1496
1526
|
resolve: serverEnvironment.resolve
|
|
@@ -1543,7 +1573,7 @@ const reactRouterVitePlugin = () => {
|
|
|
1543
1573
|
await builder.build(builder.environments.client);
|
|
1544
1574
|
let serverEnvironments = getServerEnvironmentValues(ctx, builder.environments);
|
|
1545
1575
|
await Promise.all(serverEnvironments.map(builder.build));
|
|
1546
|
-
await cleanViteManifests(environments, ctx);
|
|
1576
|
+
await cleanViteManifests([builder.environments.client, ...serverEnvironments], ctx);
|
|
1547
1577
|
}
|
|
1548
1578
|
}
|
|
1549
1579
|
};
|
|
@@ -1676,11 +1706,10 @@ const reactRouterVitePlugin = () => {
|
|
|
1676
1706
|
let cachedHandler = null;
|
|
1677
1707
|
async function getHandler() {
|
|
1678
1708
|
if (cachedHandler) return cachedHandler;
|
|
1709
|
+
invariant(viteConfig);
|
|
1710
|
+
updateServerBundlePaths();
|
|
1679
1711
|
let bundledHandlers = [];
|
|
1680
|
-
let buildManifest = ctx
|
|
1681
|
-
reactRouterConfig: ctx.reactRouterConfig,
|
|
1682
|
-
rootDirectory: ctx.rootDirectory
|
|
1683
|
-
}) : null);
|
|
1712
|
+
let { buildManifest } = ctx;
|
|
1684
1713
|
if (buildManifest?.serverBundles) {
|
|
1685
1714
|
let routesByServerBundleId = getRoutesByServerBundleId(buildManifest);
|
|
1686
1715
|
for (let bundle of Object.values(buildManifest.serverBundles)) {
|
|
@@ -1691,7 +1720,7 @@ const reactRouterVitePlugin = () => {
|
|
|
1691
1720
|
});
|
|
1692
1721
|
}
|
|
1693
1722
|
} else {
|
|
1694
|
-
let serverEntryPath = path$2.resolve(getServerBuildDirectory(
|
|
1723
|
+
let serverEntryPath = path$2.resolve(getServerBuildDirectory(viteConfig), "index.js");
|
|
1695
1724
|
let build = await import(url.pathToFileURL(serverEntryPath).href);
|
|
1696
1725
|
bundledHandlers.push({
|
|
1697
1726
|
handler: createRequestHandler(build, "production"),
|
|
@@ -1723,6 +1752,21 @@ const reactRouterVitePlugin = () => {
|
|
|
1723
1752
|
previewServer.middlewares.use(async (req, res, next) => {
|
|
1724
1753
|
if (!ctx.reactRouterConfig.ssr && (!process.env.hasOwnProperty("IS_RR_BUILD_REQUEST") ? true : process.env.IS_RR_BUILD_REQUEST !== "yes")) return next();
|
|
1725
1754
|
try {
|
|
1755
|
+
if (isApiOnlyMode(ctx.reactRouterConfig) && process.env.IS_RR_BUILD_REQUEST !== "yes") {
|
|
1756
|
+
let { basename, routeDiscovery } = ctx.reactRouterConfig;
|
|
1757
|
+
let manifestPath = routeDiscovery?.mode === "lazy" ? path$2.posix.join(basename, routeDiscovery.manifestPath ?? "/__manifest") : void 0;
|
|
1758
|
+
let pathname = new URL(req.originalUrl ?? req.url ?? "/", "http://localhost").pathname;
|
|
1759
|
+
if (!pathname.endsWith(".data") && pathname !== manifestPath) {
|
|
1760
|
+
let clientBuildDirectory = getClientBuildDirectory$1(previewServer.config);
|
|
1761
|
+
let previewPathname = decodeURIComponent(new URL(req.url ?? "/", "http://localhost").pathname);
|
|
1762
|
+
if (previewPathname.endsWith(".html") && existsSync(path$2.join(clientBuildDirectory, previewPathname))) return next();
|
|
1763
|
+
let fallbackFile = path$2.join(clientBuildDirectory, "__spa-fallback.html");
|
|
1764
|
+
if (!existsSync(fallbackFile)) fallbackFile = path$2.join(clientBuildDirectory, "index.html");
|
|
1765
|
+
res.setHeader("Content-Type", "text/html; charset=utf-8");
|
|
1766
|
+
res.end(await readFile(fallbackFile));
|
|
1767
|
+
return;
|
|
1768
|
+
}
|
|
1769
|
+
}
|
|
1726
1770
|
let handler = await getHandler();
|
|
1727
1771
|
let request = await fromNodeRequest(req, res);
|
|
1728
1772
|
await sendResponse(res, await handler(request, await reactRouterDevLoadContext(request)));
|
|
@@ -1735,9 +1779,8 @@ const reactRouterVitePlugin = () => {
|
|
|
1735
1779
|
writeBundle: { async handler() {
|
|
1736
1780
|
if (!isReactRouterServerEnvironment(ctx, this.environment.name)) return;
|
|
1737
1781
|
invariant(viteConfig);
|
|
1738
|
-
let clientBuildDirectory = getClientBuildDirectory$1(
|
|
1739
|
-
let serverBuildDirectory = this.environment.config
|
|
1740
|
-
invariant(serverBuildDirectory);
|
|
1782
|
+
let clientBuildDirectory = getClientBuildDirectory$1(viteConfig);
|
|
1783
|
+
let serverBuildDirectory = path$2.resolve(this.environment.config.root, this.environment.config.build.outDir);
|
|
1741
1784
|
let ssrViteManifest = await loadViteManifest(serverBuildDirectory);
|
|
1742
1785
|
let ssrAssetPaths = getViteManifestAssetPaths(ssrViteManifest);
|
|
1743
1786
|
let userSsrEmitAssets = viteUserConfig.environments?.ssr?.build?.ssrEmitAssets ?? viteUserConfig.environments?.ssr?.build?.emitAssets ?? viteUserConfig.build?.ssrEmitAssets ?? false;
|
|
@@ -1795,8 +1838,8 @@ const reactRouterVitePlugin = () => {
|
|
|
1795
1838
|
logHandledAssets(copiedAssetPaths, `${copiedAssetPaths.length} asset${copiedAssetPaths.length > 1 ? "s" : ""} copied from React Router server build to client assets.`);
|
|
1796
1839
|
if (handledAssetPaths.length) viteConfig.logger.info("");
|
|
1797
1840
|
} },
|
|
1798
|
-
async buildEnd() {
|
|
1799
|
-
if (viteConfig?.command !== "build") await closePluginResources();
|
|
1841
|
+
async buildEnd(error) {
|
|
1842
|
+
if (viteConfig?.command !== "build" || error) await closePluginResources();
|
|
1800
1843
|
}
|
|
1801
1844
|
},
|
|
1802
1845
|
{
|
|
@@ -1955,7 +1998,8 @@ const reactRouterVitePlugin = () => {
|
|
|
1955
1998
|
if (isRouteChunkModuleId(id)) id = id.split("?")[0];
|
|
1956
1999
|
let route = getRoute(ctx.reactRouterConfig, id);
|
|
1957
2000
|
if (!route) return;
|
|
1958
|
-
|
|
2001
|
+
let isServerEnvironment = isReactRouterServerEnvironment(ctx, this.environment.name);
|
|
2002
|
+
if (!options?.ssr && isSpaModeEnabled(ctx.reactRouterConfig) && !isApiOnlyMode(ctx.reactRouterConfig)) {
|
|
1959
2003
|
let exportNames = getExportNames(code);
|
|
1960
2004
|
let serverOnlyExports = exportNames.filter((exp) => {
|
|
1961
2005
|
if (route.id === "root" && exp === "loader") return false;
|
|
@@ -1976,6 +2020,7 @@ const reactRouterVitePlugin = () => {
|
|
|
1976
2020
|
let [filepath] = id.split("?");
|
|
1977
2021
|
let ast = parse$1(code, { sourceType: "module" });
|
|
1978
2022
|
if (!options?.ssr) removeExports(ast, SERVER_ONLY_ROUTE_EXPORTS);
|
|
2023
|
+
else if (isApiOnlyMode(ctx.reactRouterConfig) && isServerEnvironment && !isPrerenderingEnabled(ctx.reactRouterConfig) && viteCommand === "build" && route.id !== "root") removeExports(ast, CLIENT_ROUTE_EXPORTS$1);
|
|
1979
2024
|
decorateComponentExportsWithProps(ast);
|
|
1980
2025
|
return generate(ast, {
|
|
1981
2026
|
sourceMaps: true,
|
|
@@ -2092,10 +2137,7 @@ const reactRouterVitePlugin = () => {
|
|
|
2092
2137
|
prerender({
|
|
2093
2138
|
config() {
|
|
2094
2139
|
process.env.IS_RR_BUILD_REQUEST = "yes";
|
|
2095
|
-
return {
|
|
2096
|
-
buildDirectory: getClientBuildDirectory$1(ctx.reactRouterConfig),
|
|
2097
|
-
concurrency: getPrerenderConcurrencyConfig$1(ctx.reactRouterConfig)
|
|
2098
|
-
};
|
|
2140
|
+
return { concurrency: getPrerenderConcurrencyConfig$1(ctx.reactRouterConfig) };
|
|
2099
2141
|
},
|
|
2100
2142
|
async requests() {
|
|
2101
2143
|
invariant(viteConfig);
|
|
@@ -2117,7 +2159,7 @@ const reactRouterVitePlugin = () => {
|
|
|
2117
2159
|
else requests.push(createRouteRequest(prerenderPath, reactRouterConfig));
|
|
2118
2160
|
}
|
|
2119
2161
|
}
|
|
2120
|
-
if (!ctx.reactRouterConfig.ssr) requests.push(createSpaModeRequest(ctx.reactRouterConfig));
|
|
2162
|
+
if (!ctx.reactRouterConfig.ssr || ctx.reactRouterConfig.ssr === "unstable_api-only") requests.push(createSpaModeRequest(ctx.reactRouterConfig));
|
|
2121
2163
|
return requests;
|
|
2122
2164
|
},
|
|
2123
2165
|
async postProcess(request, response, metadata) {
|
|
@@ -2181,10 +2223,13 @@ const reactRouterVitePlugin = () => {
|
|
|
2181
2223
|
if (metadata.type === "spa") return;
|
|
2182
2224
|
viteConfig.logger.info(`Prerender (${metadata.type}): ${metadata.path} -> ${colors.bold(outputPath)}`);
|
|
2183
2225
|
},
|
|
2226
|
+
cleanup() {
|
|
2227
|
+
return closePluginResources();
|
|
2228
|
+
},
|
|
2184
2229
|
async finalize(buildDirectory) {
|
|
2185
2230
|
invariant(viteConfig);
|
|
2186
2231
|
let { ssr } = ctx.reactRouterConfig;
|
|
2187
|
-
if (!ssr) {
|
|
2232
|
+
if (!ssr || ssr === "unstable_api-only") {
|
|
2188
2233
|
let spaFallback = path$2.join(buildDirectory, "__spa-fallback.html");
|
|
2189
2234
|
let index = path$2.join(buildDirectory, "index.html");
|
|
2190
2235
|
let finalSpaPath;
|
|
@@ -2202,6 +2247,7 @@ const reactRouterVitePlugin = () => {
|
|
|
2202
2247
|
}),
|
|
2203
2248
|
{
|
|
2204
2249
|
name: "react-router-build-end",
|
|
2250
|
+
enforce: "post",
|
|
2205
2251
|
sharedDuringBuild: true,
|
|
2206
2252
|
config: {
|
|
2207
2253
|
order: "post",
|
|
@@ -2209,19 +2255,31 @@ const reactRouterVitePlugin = () => {
|
|
|
2209
2255
|
return { builder: { async buildApp(builder) {
|
|
2210
2256
|
try {
|
|
2211
2257
|
await buildApp?.(builder);
|
|
2212
|
-
|
|
2213
|
-
let { buildManifest, reactRouterConfig } = ctx;
|
|
2214
|
-
invariant(buildManifest, "Expected build manifest");
|
|
2215
|
-
await reactRouterConfig.buildEnd?.({
|
|
2216
|
-
buildManifest,
|
|
2217
|
-
reactRouterConfig,
|
|
2218
|
-
viteConfig
|
|
2219
|
-
});
|
|
2220
|
-
} finally {
|
|
2258
|
+
} catch (error) {
|
|
2221
2259
|
await closePluginResources();
|
|
2260
|
+
throw error;
|
|
2222
2261
|
}
|
|
2262
|
+
await closeChildCompiler();
|
|
2223
2263
|
} } };
|
|
2224
2264
|
}
|
|
2265
|
+
},
|
|
2266
|
+
buildApp: {
|
|
2267
|
+
order: "post",
|
|
2268
|
+
async handler() {
|
|
2269
|
+
try {
|
|
2270
|
+
invariant(viteConfig);
|
|
2271
|
+
let { buildManifest, reactRouterConfig } = ctx;
|
|
2272
|
+
invariant(buildManifest, "Expected build manifest");
|
|
2273
|
+
updateServerBundlePaths();
|
|
2274
|
+
await reactRouterConfig.buildEnd?.({
|
|
2275
|
+
buildManifest,
|
|
2276
|
+
reactRouterConfig,
|
|
2277
|
+
viteConfig
|
|
2278
|
+
});
|
|
2279
|
+
} finally {
|
|
2280
|
+
await closePluginResources();
|
|
2281
|
+
}
|
|
2282
|
+
}
|
|
2225
2283
|
}
|
|
2226
2284
|
},
|
|
2227
2285
|
validatePluginOrder(),
|
|
@@ -2319,7 +2377,10 @@ function isPrerenderingEnabled(reactRouterConfig) {
|
|
|
2319
2377
|
return reactRouterConfig.prerender != null && reactRouterConfig.prerender !== false;
|
|
2320
2378
|
}
|
|
2321
2379
|
function isSpaModeEnabled(reactRouterConfig) {
|
|
2322
|
-
return reactRouterConfig.ssr ===
|
|
2380
|
+
return (!reactRouterConfig.ssr || reactRouterConfig.ssr === "unstable_api-only") && !isPrerenderingEnabled(reactRouterConfig);
|
|
2381
|
+
}
|
|
2382
|
+
function isApiOnlyMode(reactRouterConfig) {
|
|
2383
|
+
return reactRouterConfig.ssr === "unstable_api-only";
|
|
2323
2384
|
}
|
|
2324
2385
|
function getStaticPrerenderPaths(routes) {
|
|
2325
2386
|
let paths = ["/"];
|
|
@@ -2512,12 +2573,8 @@ async function cleanBuildDirectory(viteConfig, ctx) {
|
|
|
2512
2573
|
recursive: true
|
|
2513
2574
|
});
|
|
2514
2575
|
}
|
|
2515
|
-
async function cleanViteManifests(
|
|
2516
|
-
let viteManifestPaths =
|
|
2517
|
-
let outDir = options.build?.outDir;
|
|
2518
|
-
invariant(outDir, `Expected build.outDir for ${environmentName}`);
|
|
2519
|
-
return path$2.join(outDir, ".vite/manifest.json");
|
|
2520
|
-
});
|
|
2576
|
+
async function cleanViteManifests(environments, ctx) {
|
|
2577
|
+
let viteManifestPaths = environments.map(({ config }) => path$2.resolve(config.root, config.build.outDir, ".vite/manifest.json"));
|
|
2521
2578
|
await Promise.all(viteManifestPaths.map(async (viteManifestPath) => {
|
|
2522
2579
|
if (!existsSync(viteManifestPath)) return;
|
|
2523
2580
|
if (!ctx.viteManifestEnabled) await rm(viteManifestPath, {
|
|
@@ -2535,7 +2592,7 @@ async function getBuildManifest({ reactRouterConfig, rootDirectory }) {
|
|
|
2535
2592
|
let { routes, serverBundles, appDirectory } = reactRouterConfig;
|
|
2536
2593
|
if (!serverBundles) return { routes };
|
|
2537
2594
|
let { normalizePath } = await import("vite");
|
|
2538
|
-
let serverBuildDirectory =
|
|
2595
|
+
let serverBuildDirectory = getDefaultServerBuildDirectory(reactRouterConfig);
|
|
2539
2596
|
let resolvedAppDirectory = path$2.resolve(rootDirectory, appDirectory);
|
|
2540
2597
|
let buildManifest = {
|
|
2541
2598
|
serverBundles: {},
|
|
@@ -2634,14 +2691,14 @@ async function getEnvironmentOptionsResolvers(ctx, viteCommand) {
|
|
|
2634
2691
|
return path$2.posix.join(assetsDir, `[name]${routeChunkSuffix}-[hash].js`);
|
|
2635
2692
|
} }
|
|
2636
2693
|
},
|
|
2637
|
-
outDir:
|
|
2694
|
+
outDir: getDefaultClientBuildDirectory(ctx.reactRouterConfig)
|
|
2638
2695
|
} }) };
|
|
2639
2696
|
let serverBundleIds = getServerBundleIds(ctx);
|
|
2640
2697
|
if (serverBundleIds) for (let serverBundleId of serverBundleIds) {
|
|
2641
2698
|
const environmentName = `${SSR_BUNDLE_PREFIX}${serverBundleId}`;
|
|
2642
|
-
environmentOptionsResolvers[environmentName] = ({ viteUserConfig }) => mergeEnvironmentOptions(getBaseServerOptions({ viteUserConfig }), { build: { outDir:
|
|
2699
|
+
environmentOptionsResolvers[environmentName] = ({ viteUserConfig }) => mergeEnvironmentOptions(getBaseServerOptions({ viteUserConfig }), { build: { outDir: getDefaultServerBuildDirectory(ctx.reactRouterConfig, { serverBundleId }) } }, viteUserConfig.environments?.ssr ?? {});
|
|
2643
2700
|
}
|
|
2644
|
-
else environmentOptionsResolvers.ssr = ({ viteUserConfig }) => mergeEnvironmentOptions(getBaseServerOptions({ viteUserConfig }), { build: { outDir:
|
|
2701
|
+
else environmentOptionsResolvers.ssr = ({ viteUserConfig }) => mergeEnvironmentOptions(getBaseServerOptions({ viteUserConfig }), { build: { outDir: getDefaultServerBuildDirectory(ctx.reactRouterConfig) } });
|
|
2645
2702
|
return environmentOptionsResolvers;
|
|
2646
2703
|
}
|
|
2647
2704
|
function resolveEnvironmentsOptions(environmentResolvers, resolverOptions) {
|
|
@@ -2677,7 +2734,7 @@ function createDataRequest(prerenderPath, reactRouterConfig, onlyRoutes, isResou
|
|
|
2677
2734
|
let url = new URL(`http://localhost${normalizedPath}`);
|
|
2678
2735
|
if (onlyRoutes?.length) url.searchParams.set("_routes", onlyRoutes.join(","));
|
|
2679
2736
|
return {
|
|
2680
|
-
request: new Request(url),
|
|
2737
|
+
request: new Request(url, { headers: { "X-React-Router-Prerender": "yes" } }),
|
|
2681
2738
|
metadata: {
|
|
2682
2739
|
type: "data",
|
|
2683
2740
|
path: prerenderPath,
|
|
@@ -2687,7 +2744,7 @@ function createDataRequest(prerenderPath, reactRouterConfig, onlyRoutes, isResou
|
|
|
2687
2744
|
}
|
|
2688
2745
|
function createRouteRequest(prerenderPath, reactRouterConfig, data) {
|
|
2689
2746
|
let normalizedPath = `${reactRouterConfig.basename}${prerenderPath}/`.replace(/\/\/+/g, "/");
|
|
2690
|
-
let headers = new Headers();
|
|
2747
|
+
let headers = new Headers({ "X-React-Router-Prerender": "yes" });
|
|
2691
2748
|
if (data) {
|
|
2692
2749
|
let encodedData = encodeURI(data);
|
|
2693
2750
|
if (encodedData.length < 8 * 1024) headers.set("X-React-Router-Prerender-Data", encodedData);
|
|
@@ -2702,8 +2759,13 @@ function createRouteRequest(prerenderPath, reactRouterConfig, data) {
|
|
|
2702
2759
|
}
|
|
2703
2760
|
function createResourceRouteRequest(prerenderPath, reactRouterConfig, requestInit) {
|
|
2704
2761
|
let normalizedPath = `${reactRouterConfig.basename}${prerenderPath}/`.replace(/\/\/+/g, "/").replace(/\/$/g, "");
|
|
2762
|
+
let headers = new Headers(requestInit?.headers);
|
|
2763
|
+
headers.set("X-React-Router-Prerender", "yes");
|
|
2705
2764
|
return {
|
|
2706
|
-
request: new Request(`http://localhost${normalizedPath}`,
|
|
2765
|
+
request: new Request(`http://localhost${normalizedPath}`, {
|
|
2766
|
+
...requestInit,
|
|
2767
|
+
headers
|
|
2768
|
+
}),
|
|
2707
2769
|
metadata: {
|
|
2708
2770
|
type: "resource",
|
|
2709
2771
|
path: prerenderPath
|
|
@@ -2863,6 +2925,38 @@ const ENSURE_CLIENT_ROUTE_MODULE_CHUNK_FOR_HMR = `
|
|
|
2863
2925
|
import * as ___EnsureClientRouteModuleForHMR_REACT___ from "react";
|
|
2864
2926
|
export function EnsureClientRouteModuleForHMR___() { return ___EnsureClientRouteModuleForHMR_REACT___.createElement(___EnsureClientRouteModuleForHMR_REACT___.Fragment, null) }
|
|
2865
2927
|
`;
|
|
2928
|
+
function createEmptySourceMap() {
|
|
2929
|
+
return {
|
|
2930
|
+
version: 3,
|
|
2931
|
+
names: [],
|
|
2932
|
+
sources: [],
|
|
2933
|
+
mappings: ""
|
|
2934
|
+
};
|
|
2935
|
+
}
|
|
2936
|
+
function generateRouteModule(code, map, filename) {
|
|
2937
|
+
const ast = parse$1(code, { sourceType: "module" });
|
|
2938
|
+
const generatorOptions = {
|
|
2939
|
+
sourceMaps: true,
|
|
2940
|
+
sourceFileName: filename,
|
|
2941
|
+
inputSourceMap: map
|
|
2942
|
+
};
|
|
2943
|
+
return {
|
|
2944
|
+
ast,
|
|
2945
|
+
generate: () => generate(ast, generatorOptions)
|
|
2946
|
+
};
|
|
2947
|
+
}
|
|
2948
|
+
function prependUnmappedCode(prefix, generated) {
|
|
2949
|
+
if (generated.map) generated.map.mappings = ";".repeat(prefix.match(/\n/g)?.length ?? 0) + generated.map.mappings;
|
|
2950
|
+
return {
|
|
2951
|
+
code: prefix + generated.code,
|
|
2952
|
+
map: generated.map
|
|
2953
|
+
};
|
|
2954
|
+
}
|
|
2955
|
+
function appendUnmappedCode(generated, code) {
|
|
2956
|
+
if (!generated.code.endsWith("\n") && !code.startsWith("\n")) code = "\n" + code;
|
|
2957
|
+
if (generated.map) generated.map.mappings += ";A".repeat(code.match(/\n/g)?.length ?? 0);
|
|
2958
|
+
generated.code += code;
|
|
2959
|
+
}
|
|
2866
2960
|
function virtualRouteModulesPlugin({ enforceSplitRouteModules, environments: { client = ["client", "ssr"], server = ["rsc"] } = {}, getRouteIdForFile, isRootRouteModule, transformToJs, shouldTransform }) {
|
|
2867
2961
|
let clientEnvironments = new Set(client);
|
|
2868
2962
|
let serverEnvironments = new Set(server);
|
|
@@ -2898,7 +2992,10 @@ function virtualRouteModulesPlugin({ enforceSplitRouteModules, environments: { c
|
|
|
2898
2992
|
}
|
|
2899
2993
|
});
|
|
2900
2994
|
}
|
|
2901
|
-
return {
|
|
2995
|
+
return {
|
|
2996
|
+
code: "\"use client\";\n" + result,
|
|
2997
|
+
map: createEmptySourceMap()
|
|
2998
|
+
};
|
|
2902
2999
|
}
|
|
2903
3000
|
async function createServerRouteEntry(id, code, isRootRouteModule, routeId) {
|
|
2904
3001
|
let result = "";
|
|
@@ -2938,16 +3035,19 @@ ${result}`;
|
|
|
2938
3035
|
}
|
|
2939
3036
|
});
|
|
2940
3037
|
}
|
|
2941
|
-
return {
|
|
3038
|
+
return {
|
|
3039
|
+
code: result,
|
|
3040
|
+
map: createEmptySourceMap()
|
|
3041
|
+
};
|
|
2942
3042
|
}
|
|
2943
|
-
function createServerRouteModule(code) {
|
|
2944
|
-
const ast =
|
|
3043
|
+
function createServerRouteModule(code, map, filename) {
|
|
3044
|
+
const { ast, generate } = generateRouteModule(code, map, filename);
|
|
2945
3045
|
removeExports(ast, CLIENT_ROUTE_EXPORTS);
|
|
2946
|
-
return generate(
|
|
3046
|
+
return generate();
|
|
2947
3047
|
}
|
|
2948
|
-
async function createClientRouteModuleChunk(id, code, chunk, routeId, isRootRouteModule, isDevMode) {
|
|
3048
|
+
async function createClientRouteModuleChunk(id, code, chunk, routeId, isRootRouteModule, isDevMode, map, filename) {
|
|
2949
3049
|
let routeChunks = detectRouteChunks(cache, id, code, isRootRouteModule);
|
|
2950
|
-
const ast =
|
|
3050
|
+
const { ast, generate } = generateRouteModule(code, map, filename);
|
|
2951
3051
|
const { staticExports } = await parseRouteExports(code);
|
|
2952
3052
|
if (chunk === "shared") removeExports(ast, [...SERVER_ROUTE_EXPORTS, ...routeChunks.chunkedExports]);
|
|
2953
3053
|
else {
|
|
@@ -2955,33 +3055,26 @@ ${result}`;
|
|
|
2955
3055
|
toRemove.delete(chunk);
|
|
2956
3056
|
removeExports(ast, Array.from(toRemove));
|
|
2957
3057
|
}
|
|
2958
|
-
let result = "\"use client\";\n"
|
|
3058
|
+
let result = prependUnmappedCode("\"use client\";\n", generate());
|
|
2959
3059
|
if (chunk === "shared") {
|
|
2960
|
-
if (isRootRouteModule && !staticExports.includes("ErrorBoundary") && !staticExports.includes("ServerErrorBoundary"))
|
|
2961
|
-
|
|
2962
|
-
|
|
2963
|
-
|
|
2964
|
-
|
|
2965
|
-
|
|
2966
|
-
result += `}\n`;
|
|
2967
|
-
}
|
|
2968
|
-
result += ENSURE_CLIENT_ROUTE_MODULE_CHUNK_FOR_HMR;
|
|
3060
|
+
if (isRootRouteModule && !staticExports.includes("ErrorBoundary") && !staticExports.includes("ServerErrorBoundary")) appendUnmappedCode(result, `
|
|
3061
|
+
import { createElement as __rr_createElement } from "react";
|
|
3062
|
+
import { UNSAFE_RSCDefaultRootErrorBoundary } from "react-router";
|
|
3063
|
+
export function ErrorBoundary() {
|
|
3064
|
+
return __rr_createElement(UNSAFE_RSCDefaultRootErrorBoundary, { hasRootLayout: ${staticExports.includes("Layout") || staticExports.includes("ServerLayout")} });\n}\n`);
|
|
3065
|
+
appendUnmappedCode(result, ENSURE_CLIENT_ROUTE_MODULE_CHUNK_FOR_HMR);
|
|
2969
3066
|
}
|
|
2970
3067
|
let hasAction = staticExports.includes("action");
|
|
2971
3068
|
let hasLoader = staticExports.includes("loader");
|
|
2972
3069
|
let hasComponent = staticExports.includes("default") || staticExports.includes("ServerComponent");
|
|
2973
3070
|
let hasErrorBoundary = staticExports.includes("ErrorBoundary") || staticExports.includes("ServerErrorBoundary");
|
|
2974
|
-
if (isDevMode) {
|
|
2975
|
-
result += `export function ReactRouterHMRMeta___() {return null;};\n`;
|
|
2976
|
-
result += `Object.assign(ReactRouterHMRMeta___, {
|
|
3071
|
+
if (isDevMode) appendUnmappedCode(result, `export function ReactRouterHMRMeta___() {return null;};\nObject.assign(ReactRouterHMRMeta___, {
|
|
2977
3072
|
hasAction: ${JSON.stringify(hasAction)},
|
|
2978
3073
|
hasComponent: ${JSON.stringify(hasComponent)},
|
|
2979
3074
|
hasErrorBoundary: ${JSON.stringify(hasErrorBoundary)},
|
|
2980
3075
|
hasLoader: ${JSON.stringify(hasLoader)},
|
|
2981
3076
|
hasClientLoader: ${JSON.stringify(staticExports.includes("clientLoader"))},
|
|
2982
|
-
});\n
|
|
2983
|
-
result += `\nif (import.meta.hot) {\n`;
|
|
2984
|
-
result += ` import.meta.hot.accept((mod) => {
|
|
3077
|
+
});\n\nif (import.meta.hot) {\n import.meta.hot.accept((mod) => {
|
|
2985
3078
|
if (typeof __reactRouterDataRouter === "object") {
|
|
2986
3079
|
__reactRouterDataRouter._updateRoutesForHMR(new Map([[${JSON.stringify(routeId)}, {
|
|
2987
3080
|
routeModule: mod,
|
|
@@ -2995,10 +3088,8 @@ ${result}`;
|
|
|
2995
3088
|
}
|
|
2996
3089
|
}
|
|
2997
3090
|
});
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
}
|
|
3001
|
-
return { code: result };
|
|
3091
|
+
}\n`);
|
|
3092
|
+
return result;
|
|
3002
3093
|
}
|
|
3003
3094
|
return {
|
|
3004
3095
|
name: "react-router-rsc-virtual-route-modules",
|
|
@@ -3010,12 +3101,13 @@ ${result}`;
|
|
|
3010
3101
|
let isClientEnvironment = clientEnvironments.has(this.environment.name);
|
|
3011
3102
|
let isServerEnvironment = serverEnvironments.has(this.environment.name);
|
|
3012
3103
|
if (!isClientEnvironment && !isServerEnvironment) return;
|
|
3013
|
-
let
|
|
3104
|
+
let transformed = await transformToJs(_code, filename);
|
|
3105
|
+
let code = transformed.code;
|
|
3014
3106
|
let searchParams = rest.length > 0 ? new URLSearchParams(rest.join("?")) : null;
|
|
3015
3107
|
let clientRouteModuleType = searchParams?.get("client-route-module");
|
|
3016
3108
|
let isServerRouteModule = searchParams?.has("server-route-module");
|
|
3017
|
-
if (clientRouteModuleType) return await createClientRouteModuleChunk(id, code, clientRouteModuleType, routeId, isRootRouteModule(filename), this.environment.mode === "dev");
|
|
3018
|
-
if (isServerRouteModule) return createServerRouteModule(code);
|
|
3109
|
+
if (clientRouteModuleType) return await createClientRouteModuleChunk(id, code, clientRouteModuleType, routeId, isRootRouteModule(filename), this.environment.mode === "dev", transformed.map, filename);
|
|
3110
|
+
if (isServerRouteModule) return createServerRouteModule(code, transformed.map, filename);
|
|
3019
3111
|
if (isClientEnvironment) return await createClientRouteEntry(id, code, isRootRouteModule(filename), routeId);
|
|
3020
3112
|
return await createServerRouteEntry(id, code, isRootRouteModule(filename), routeId);
|
|
3021
3113
|
}
|
|
@@ -3181,7 +3273,7 @@ function reactRouterRSCVitePlugin() {
|
|
|
3181
3273
|
await preloadVite();
|
|
3182
3274
|
let vite = getVite();
|
|
3183
3275
|
let lang = getTransformLanguage(filename);
|
|
3184
|
-
return
|
|
3276
|
+
return "transformWithOxc" in vite && typeof vite.transformWithOxc === "function" ? await vite.transformWithOxc(code, filename, {
|
|
3185
3277
|
lang,
|
|
3186
3278
|
jsx: {
|
|
3187
3279
|
runtime: "automatic",
|
|
@@ -3194,7 +3286,7 @@ function reactRouterRSCVitePlugin() {
|
|
|
3194
3286
|
format: "esm",
|
|
3195
3287
|
jsx: "automatic",
|
|
3196
3288
|
jsxDev: viteCommand !== "build"
|
|
3197
|
-
})
|
|
3289
|
+
});
|
|
3198
3290
|
}
|
|
3199
3291
|
async function getClientVersion(source) {
|
|
3200
3292
|
const digest = await globalThis.crypto.subtle.digest("SHA-256", new TextEncoder().encode(source));
|
|
@@ -3223,6 +3315,7 @@ function reactRouterRSCVitePlugin() {
|
|
|
3223
3315
|
if (userConfig.buildEnd) errors.push("buildEnd");
|
|
3224
3316
|
if (userConfig.presets?.length) errors.push("presets");
|
|
3225
3317
|
if (userConfig.serverBundles) errors.push("serverBundles");
|
|
3318
|
+
if (userConfig.ssr === "unstable_api-only") errors.push("ssr: \"unstable_api-only\"");
|
|
3226
3319
|
if (errors.length) return `RSC Framework Mode does not currently support the following React Router config:\n${errors.map((x) => ` - ${x}`).join("\n")}\n`;
|
|
3227
3320
|
}
|
|
3228
3321
|
});
|
|
@@ -3240,6 +3333,7 @@ function reactRouterRSCVitePlugin() {
|
|
|
3240
3333
|
});
|
|
3241
3334
|
let routeFiles = new Set(Object.values(config.routes).map((route) => resolveRelativeRouteFilePath(route, config)));
|
|
3242
3335
|
return {
|
|
3336
|
+
__reactRouterBuildContext: { close: () => configLoader.close() },
|
|
3243
3337
|
resolve: { dedupe: [
|
|
3244
3338
|
"react",
|
|
3245
3339
|
"react/jsx-runtime",
|
|
@@ -3355,7 +3449,7 @@ format: config.serverModuleFormat }
|
|
|
3355
3449
|
});
|
|
3356
3450
|
},
|
|
3357
3451
|
configurePreviewServer(previewServer) {
|
|
3358
|
-
const clientBuildDirectory = getClientBuildDirectory(
|
|
3452
|
+
const clientBuildDirectory = getClientBuildDirectory(resolvedViteConfig);
|
|
3359
3453
|
if ((config.prerender || config.ssr === false) && process.env.IS_RR_BUILD_REQUEST !== "yes") {
|
|
3360
3454
|
previewServer.middlewares.use(async (req, res, next) => {
|
|
3361
3455
|
try {
|
|
@@ -3390,11 +3484,8 @@ format: config.serverModuleFormat }
|
|
|
3390
3484
|
};
|
|
3391
3485
|
}
|
|
3392
3486
|
},
|
|
3393
|
-
|
|
3394
|
-
|
|
3395
|
-
async handler() {
|
|
3396
|
-
await configLoader.close();
|
|
3397
|
-
}
|
|
3487
|
+
async buildEnd(error) {
|
|
3488
|
+
if (error) await configLoader.close();
|
|
3398
3489
|
}
|
|
3399
3490
|
},
|
|
3400
3491
|
(() => {
|
|
@@ -3561,12 +3652,10 @@ export default assetsManifest.clientVersion;
|
|
|
3561
3652
|
warnOnClientSourceMaps(),
|
|
3562
3653
|
prerender({
|
|
3563
3654
|
config() {
|
|
3564
|
-
return {
|
|
3565
|
-
buildDirectory: getClientBuildDirectory(config),
|
|
3566
|
-
concurrency: getPrerenderConcurrencyConfig(config)
|
|
3567
|
-
};
|
|
3655
|
+
return { concurrency: getPrerenderConcurrencyConfig(config) };
|
|
3568
3656
|
},
|
|
3569
3657
|
logFile: (path) => logger.info(`Prerendered ${colors.bold(path)}`),
|
|
3658
|
+
cleanup: () => configLoader.close(),
|
|
3570
3659
|
async requests() {
|
|
3571
3660
|
const prerenderPaths = new Set(await getPrerenderPaths(config.prerender, config.ssr, config.routes, true));
|
|
3572
3661
|
let basename = !config.basename || config.basename === "/" ? "/" : config.basename.endsWith("/") ? config.basename : config.basename + "/";
|
|
@@ -3622,7 +3711,18 @@ export default assetsManifest.clientVersion;
|
|
|
3622
3711
|
}
|
|
3623
3712
|
return files;
|
|
3624
3713
|
}
|
|
3625
|
-
})
|
|
3714
|
+
}),
|
|
3715
|
+
{
|
|
3716
|
+
name: "react-router/rsc/build-end",
|
|
3717
|
+
enforce: "post",
|
|
3718
|
+
sharedDuringBuild: true,
|
|
3719
|
+
buildApp: {
|
|
3720
|
+
order: "post",
|
|
3721
|
+
async handler() {
|
|
3722
|
+
await configLoader.close();
|
|
3723
|
+
}
|
|
3724
|
+
}
|
|
3725
|
+
}
|
|
3626
3726
|
];
|
|
3627
3727
|
}
|
|
3628
3728
|
const virtual = {
|
|
@@ -3654,7 +3754,7 @@ function createRSCOptimizeDepsRouteModulesPlugin({ routeFiles, transformToJs })
|
|
|
3654
3754
|
let normalizedFilename = getVite().normalizePath(filename);
|
|
3655
3755
|
if (!routeFiles.has(normalizedFilename)) return;
|
|
3656
3756
|
return {
|
|
3657
|
-
code: createClientRouteModuleForOptimizeDepsScan(await transformToJs(code, filename)).code,
|
|
3757
|
+
code: createClientRouteModuleForOptimizeDepsScan((await transformToJs(code, filename)).code).code,
|
|
3658
3758
|
map: null,
|
|
3659
3759
|
moduleType: "js"
|
|
3660
3760
|
};
|
|
@@ -3662,7 +3762,7 @@ function createRSCOptimizeDepsRouteModulesPlugin({ routeFiles, transformToJs })
|
|
|
3662
3762
|
}
|
|
3663
3763
|
};
|
|
3664
3764
|
}
|
|
3665
|
-
const getClientBuildDirectory = (
|
|
3765
|
+
const getClientBuildDirectory = (viteConfig) => path$1.resolve(viteConfig.root, viteConfig.environments.client.build.outDir);
|
|
3666
3766
|
function getPrerenderConcurrencyConfig(reactRouterConfig) {
|
|
3667
3767
|
let concurrency = 1;
|
|
3668
3768
|
let { prerender } = reactRouterConfig;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@react-router/dev",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "8.
|
|
4
|
+
"version": "8.5.1",
|
|
5
5
|
"description": "Dev tools and CLI for React Router",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"react",
|
|
@@ -107,7 +107,7 @@
|
|
|
107
107
|
"semver": "^7.8.1",
|
|
108
108
|
"tinyglobby": "^0.2.16",
|
|
109
109
|
"valibot": "^1.4.1",
|
|
110
|
-
"@react-router/node": "8.
|
|
110
|
+
"@react-router/node": "8.5.1"
|
|
111
111
|
},
|
|
112
112
|
"devDependencies": {
|
|
113
113
|
"@babel/plugin-syntax-jsx": "^7.29.7",
|
|
@@ -132,8 +132,8 @@
|
|
|
132
132
|
"vite": "^7.0.0",
|
|
133
133
|
"wireit": "0.14.12",
|
|
134
134
|
"wrangler": "^4.95.0",
|
|
135
|
-
"react-router": "
|
|
136
|
-
"
|
|
135
|
+
"@react-router/serve": "8.5.1",
|
|
136
|
+
"react-router": "^8.5.1"
|
|
137
137
|
},
|
|
138
138
|
"peerDependencies": {
|
|
139
139
|
"@vitejs/plugin-rsc": "~0.5.26",
|
|
@@ -141,8 +141,8 @@
|
|
|
141
141
|
"typescript": "^5.1.0 || ^6.0.0 || ^7.0.0",
|
|
142
142
|
"vite": "^7.0.0 || ^8.0.0",
|
|
143
143
|
"wrangler": "^4.0.0",
|
|
144
|
-
"@react-router/serve": "^8.
|
|
145
|
-
"react-router": "^8.
|
|
144
|
+
"@react-router/serve": "^8.5.1",
|
|
145
|
+
"react-router": "^8.5.1"
|
|
146
146
|
},
|
|
147
147
|
"peerDependenciesMeta": {
|
|
148
148
|
"@vitejs/plugin-rsc": {
|