@react-router/dev 8.3.1 → 8.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,49 @@
1
1
  # `@react-router/dev`
2
2
 
3
+ ## v8.5.0
4
+
5
+ ### Patch Changes
6
+
7
+ - 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))
8
+ - Fix intermittent `Prerender: Request failed for ... connect ECONNREFUSED` errors during prerendering ([#15325](https://github.com/remix-run/react-router/pull/15325))
9
+ - Send requests to the address the Vite preview server bound to
10
+ - Avoid re-resolving `localhost` for each request, which could select a different address family (`127.0.0.1` vs `::1`)
11
+
12
+ ### Unstable Changes
13
+
14
+ ⚠️ _[Unstable features](https://reactrouter.com/community/api-development-strategy#unstable-flags) are not recommended for production use_
15
+
16
+ - 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))
17
+ - Generate a root-only SPA shell when prerendering is disabled
18
+ - Support prerendered pages and data files alongside runtime loaders and actions, with a SPA fallback for non-prerendered paths
19
+ - Default API-only builds to lazy route discovery
20
+ - Reject API-only configuration in RSC Framework Mode
21
+ - Preserve server-only route exports in additional Vite server environments in both API-only and SSR modes
22
+ - Serve prerendered pages and the SPA fallback in Vite preview while retaining live data requests and route discovery
23
+ - 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))
24
+ - Fix source maps for route modules in unstable RSC Framework Mode ([#15479](https://github.com/remix-run/react-router/pull/15479))
25
+ - 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))
26
+ - Updated dependencies:
27
+ - [`react-router@8.5.0`](https://github.com/remix-run/react-router/releases/tag/react-router@8.5.0)
28
+ - [`@react-router/node@8.5.0`](https://github.com/remix-run/react-router/releases/tag/@react-router/node@8.5.0)
29
+ - [`@react-router/serve@8.5.0`](https://github.com/remix-run/react-router/releases/tag/@react-router/serve@8.5.0)
30
+
31
+ ## v8.4.0
32
+
33
+ ### Patch Changes
34
+
35
+ - Fix action submissions behind an HTTPS reverse proxy in `react-router dev` and `vite preview` by using `X-Forwarded-Proto` when constructing `request.url` ([#15466](https://github.com/remix-run/react-router/pull/15466))
36
+ - No React Router configuration is required
37
+ - The URL host continues to come from `Host`, not `X-Forwarded-Host`
38
+ - Configure reverse proxies to overwrite client-supplied `X-Forwarded-Proto` headers
39
+ - Do not expose dev or preview servers publicly
40
+ - Pass development conditions as CLI flags when relaunching the dev process ([#15435](https://github.com/remix-run/react-router/pull/15435))
41
+ - Fix stack trace locations for split route modules when source maps are enabled in the `reactRouter` Vite plugin ([#15440](https://github.com/remix-run/react-router/pull/15440))
42
+ - Updated dependencies:
43
+ - [`react-router@8.4.0`](https://github.com/remix-run/react-router/releases/tag/react-router@8.4.0)
44
+ - [`@react-router/node@8.4.0`](https://github.com/remix-run/react-router/releases/tag/@react-router/node@8.4.0)
45
+ - [`@react-router/serve@8.4.0`](https://github.com/remix-run/react-router/releases/tag/@react-router/serve@8.4.0)
46
+
3
47
  ## v8.3.1
4
48
 
5
49
  ### Patch Changes
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @react-router/dev v8.3.1
2
+ * @react-router/dev v8.5.0
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-DxFMuBQP.js";
11
+ import { _ as getVite, v as preloadVite } from "./typegen-CiHN93zF.js";
12
12
  //#region vite/build.ts
13
13
  async function build(root, viteBuildOptions) {
14
14
  await preloadVite();
package/dist/cli/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * @react-router/dev v8.3.1
3
+ * @react-router/dev v8.5.0
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-DxFMuBQP.js";
12
+ import { _ as getVite, l as hasNodeDependency, n as watch, t as run$1, u as loadConfig, v as preloadVite } from "../typegen-CiHN93zF.js";
13
13
  import { createRequire } from "node:module";
14
14
  import { parseArgs } from "node:util";
15
15
  import semver from "semver";
@@ -107,20 +107,34 @@ async function hasReactRouterRscPlugin({ root, viteBuildOptions: { config, logLe
107
107
  //#endregion
108
108
  //#region restart-with-conditions.ts
109
109
  /**
110
- * Restarts the current Node process, appending new flags to the
111
- * existing NODE_OPTIONS. SIGINT/SIGTERM are always forwarded to the child.
110
+ * Build the child process invocation used to relaunch the CLI with extra flags.
111
+ *
112
+ * Extra flags are placed on argv immediately after the runtime binary. Putting
113
+ * them in NODE_OPTIONS is not portable: Bun silently ignores `--conditions`
114
+ * there, so the child would restart again and hit the already-restarted guard.
112
115
  */
113
- function restartWithMergedOptions(nodeOptions) {
114
- if (process$1.env.REACT_ROUTER_DEV_RESTARTED === "true") throw new Error("restartWithMergedOptions() was called, but the process has already been restarted. This is likely a bug in @react-router/dev.");
115
- const mergedOptions = [process$1.env.NODE_OPTIONS, nodeOptions].filter(Boolean).join(" ").trim();
116
- console.log(`[restart] Relaunching with NODE_OPTIONS: ${mergedOptions}`);
117
- const [cmd, ...args] = process$1.argv;
118
- const child = spawn(cmd, args, {
116
+ function resolveRestartSpawn(argv, extraOptions, env) {
117
+ const extraArgs = extraOptions.split(/\s+/).filter(Boolean);
118
+ const [command, ...args] = argv;
119
+ return {
120
+ command,
121
+ args: [...extraArgs, ...args],
119
122
  env: {
120
- ...process$1.env,
121
- NODE_OPTIONS: mergedOptions,
123
+ ...env,
122
124
  REACT_ROUTER_DEV_RESTARTED: "true"
123
- },
125
+ }
126
+ };
127
+ }
128
+ /**
129
+ * Restarts the current process with extra CLI flags after argv[0].
130
+ * SIGINT/SIGTERM are always forwarded to the child.
131
+ */
132
+ function restartWithMergedOptions(nodeOptions) {
133
+ if (process$1.env.REACT_ROUTER_DEV_RESTARTED === "true") throw new Error("restartWithMergedOptions() was called, but the process has already been restarted. This is likely a bug in @react-router/dev.");
134
+ const { command, args, env } = resolveRestartSpawn(process$1.argv, nodeOptions, process$1.env);
135
+ console.log(`[restart] Relaunching with ${nodeOptions}`);
136
+ const child = spawn(command, args, {
137
+ env,
124
138
  stdio: "inherit"
125
139
  });
126
140
  let signalHandlers = ["SIGINT", "SIGTERM"].map((sig) => {
@@ -158,7 +172,7 @@ async function routes(rootDirectory, flags = {}) {
158
172
  }
159
173
  async function build(root, options = {}) {
160
174
  root = resolveRootDirectory(root, options);
161
- let { build } = await import("../build-Ou3B3epu.js");
175
+ let { build } = await import("../build-ZbZgdE7Y.js");
162
176
  if (options.profile) await start();
163
177
  try {
164
178
  await build(root, options);
@@ -168,7 +182,7 @@ async function build(root, options = {}) {
168
182
  }
169
183
  async function dev(root, options = {}) {
170
184
  if (developmentConditionEnabled) {
171
- let { dev } = await import("../dev-DFccbHpq.js");
185
+ let { dev } = await import("../dev-DGFm0uWr.js");
172
186
  if (options.profile) await start();
173
187
  exitHook(() => stop(console.info));
174
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
- * Enable server-side rendering for your application. Disable to use "SPA
144
- * Mode", which will request the `/` path at build-time and save it as an
145
- * `index.html` file with your assets so your application can be deployed as a
146
- * SPA without server-rendering. Default's to `true`.
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
- ssr?: boolean;
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
- * Enable server-side rendering for your application. Disable to use "SPA
260
- * Mode", which will request the `/` path at build-time and save it as an
261
- * `index.html` file with your assets so your application can be deployed as a
262
- * SPA without server-rendering. Default's to `true`.
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
- ssr: boolean;
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-t89niiFv.js";
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.3.1
2
+ * @react-router/dev v8.5.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @react-router/dev v8.3.1
2
+ * @react-router/dev v8.5.0
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-DxFMuBQP.js";
11
+ import { _ as getVite, v as preloadVite } from "./typegen-CiHN93zF.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
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @react-router/dev v8.3.1
2
+ * @react-router/dev v8.5.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
package/dist/routes.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @react-router/dev v8.3.1
2
+ * @react-router/dev v8.5.0
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-C-NBxWG3.js";
11
+ import { a as prefix, i as layout, n as getAppDirectory, o as relative, r as index, s as route } from "./routes-Cyup1Gnm.js";
12
12
  export { getAppDirectory, index, layout, prefix, relative, route };
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @react-router/dev v8.3.1
2
+ * @react-router/dev v8.5.0
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-C-NBxWG3.js";
11
+ import { c as setAppDirectory, l as validateRouteConfig, t as configRoutesToRouteManifest, u as invariant } from "./routes-Cyup1Gnm.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.3.1
2
+ * @react-router/dev v8.5.0
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-DxFMuBQP.js";
12
- import { u as invariant } from "./routes-C-NBxWG3.js";
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-CiHN93zF.js";
12
+ import { u as invariant } from "./routes-Cyup1Gnm.js";
13
13
  import { createRequire } from "node:module";
14
14
  import colors from "picocolors";
15
15
  import { existsSync, readFileSync, readdirSync } from "node:fs";
@@ -37,7 +37,13 @@ import { readFile as readFile$1 } from "fs/promises";
37
37
  async function fromNodeRequest(nodeReq, nodeRes) {
38
38
  invariant(nodeReq.originalUrl, "Expected `nodeReq.originalUrl` to be defined");
39
39
  nodeReq.url = nodeReq.originalUrl;
40
- return createRequest(nodeReq, nodeRes);
40
+ return createRequest(nodeReq, nodeRes, { protocol: getForwardedProtocol(nodeReq) });
41
+ }
42
+ function getForwardedProtocol(nodeReq) {
43
+ let forwardedProto = nodeReq.headers["x-forwarded-proto"];
44
+ let proto = (Array.isArray(forwardedProto) ? forwardedProto[0] : forwardedProto)?.split(",")[0].trim().toLowerCase();
45
+ if (proto?.endsWith(":")) proto = proto.slice(0, -1);
46
+ return proto === "http" || proto === "https" ? `${proto}:` : void 0;
41
47
  }
42
48
  //#endregion
43
49
  //#region vite/resolve-file-url.ts
@@ -108,7 +114,8 @@ const findDeps = async (vite, node, deps) => {
108
114
  }
109
115
  }
110
116
  async function addFromUrl(url) {
111
- let node = await vite.moduleGraph.getModuleByUrl(url);
117
+ let ssrNode = await vite.environments.ssr.moduleGraph.getModuleByUrl(url);
118
+ let node = ssrNode?.id ? vite.moduleGraph.getModuleById(ssrNode.id) : void 0;
112
119
  if (node) await addFromNode(node);
113
120
  }
114
121
  if (node.ssrTransformResult) {
@@ -614,9 +621,9 @@ const routeChunkExportNames = [
614
621
  ];
615
622
  const mainChunkName = "main";
616
623
  const routeChunkNames = ["main", ...routeChunkExportNames];
617
- function getRouteChunkCode(code, chunkName, cache, cacheKey) {
618
- if (chunkName === mainChunkName) return omitChunkedExports(code, routeChunkExportNames, {}, cache, cacheKey);
619
- return getChunkedExport(code, chunkName, {}, cache, cacheKey);
624
+ function getRouteChunkCode(code, chunkName, cache, cacheKey, generateOptions = {}) {
625
+ if (chunkName === mainChunkName) return omitChunkedExports(code, routeChunkExportNames, generateOptions, cache, cacheKey);
626
+ return getChunkedExport(code, chunkName, generateOptions, cache, cacheKey);
620
627
  }
621
628
  const routeChunkQueryStringPrefix = "?route-chunk=";
622
629
  const routeChunkQueryStrings = {
@@ -910,7 +917,7 @@ async function nodeHttpFetch(request, { signal }) {
910
917
  return new Promise((resolve, reject) => {
911
918
  const req = http.request({
912
919
  protocol: url.protocol,
913
- hostname: url.hostname,
920
+ hostname: url.hostname.replace(/^\[|\]$/g, ""),
914
921
  port: url.port || void 0,
915
922
  path: url.pathname + url.search,
916
923
  method: request.method,
@@ -960,9 +967,15 @@ async function startPreviewServer(viteConfig) {
960
967
  }
961
968
  }
962
969
  function getResolvedUrl(previewServer) {
963
- const baseUrl = previewServer.resolvedUrls?.local[0];
964
- if (!baseUrl) throw new Error("Prerender: No resolved URL is available from the Vite preview server");
965
- return new URL(baseUrl);
970
+ const printableUrl = previewServer.resolvedUrls?.local[0];
971
+ const address = previewServer.httpServer?.address();
972
+ if (address && typeof address === "object" && address.address !== "::" && address.address !== "0.0.0.0") {
973
+ const protocol = printableUrl ? new URL(printableUrl).protocol : "http:";
974
+ const hostname = address.family === "IPv6" ? `[${address.address}]` : address.address;
975
+ return new URL(`${protocol}//${hostname}:${address.port}/`);
976
+ }
977
+ if (!printableUrl) throw new Error("Prerender: No resolved URL is available from the Vite preview server");
978
+ return new URL(printableUrl);
966
979
  }
967
980
  //#endregion
968
981
  //#region vite/plugin.ts
@@ -1231,14 +1244,16 @@ const reactRouterVitePlugin = () => {
1231
1244
  import * as entryServer from ${JSON.stringify(resolveFileUrl(ctx, ctx.entryServerFilePath, { publicPath: ctx.publicPath }))};
1232
1245
  ${Object.keys(routes).map((key, index) => {
1233
1246
  let route = routes[key];
1234
- if (isSpaMode && key !== "root") return `const route${index} = { default: () => null };`;
1247
+ if (isSpaMode && !isApiOnlyMode(ctx.reactRouterConfig) && key !== "root") return `const route${index} = { default: () => null };`;
1235
1248
  else return `import * as route${index} from ${JSON.stringify(resolveFileUrl(ctx, resolveRelativeRouteFilePath(route, ctx.reactRouterConfig), { publicPath: ctx.publicPath }))};`;
1236
1249
  }).join("\n")}
1237
1250
  export { default as assets } from ${JSON.stringify(virtual$1.serverManifest.id)};
1238
1251
  export const assetsBuildDirectory = ${JSON.stringify(path$2.relative(ctx.rootDirectory, getClientBuildDirectory$1(ctx.reactRouterConfig)))};
1239
1252
  export const basename = ${JSON.stringify(ctx.reactRouterConfig.basename)};
1240
1253
  export const future = ${JSON.stringify(ctx.reactRouterConfig.future)};
1241
- export const ssr = ${ctx.reactRouterConfig.ssr};
1254
+ export const ssr = ${Boolean(ctx.reactRouterConfig.ssr)};
1255
+ export const unstable_apiOnly = ${isApiOnlyMode(ctx.reactRouterConfig)};
1256
+ export const unstable_apiServerOrigin = ${isApiOnlyMode(ctx.reactRouterConfig) ? JSON.stringify(ctx.reactRouterConfig.unstable_apiServerOrigin) : "undefined"};
1242
1257
  export const isSpaMode = ${isSpaMode};
1243
1258
  export const prerender = ${JSON.stringify(prerenderPaths)};
1244
1259
  export const routeDiscovery = ${JSON.stringify(ctx.reactRouterConfig.routeDiscovery)};
@@ -1484,7 +1499,7 @@ const reactRouterVitePlugin = () => {
1484
1499
  invariant(serverEnvironment);
1485
1500
  return {
1486
1501
  __reactRouterPluginContext: ctx,
1487
- appType: viteCommand === "serve" && _viteConfigEnv.mode === "production" && ctx.reactRouterConfig.ssr === false ? "spa" : "custom",
1502
+ appType: viteCommand === "serve" && _viteConfigEnv.mode === "production" && (!ctx.reactRouterConfig.ssr || ctx.reactRouterConfig.ssr === "unstable_api-only") ? isApiOnlyMode(ctx.reactRouterConfig) ? "mpa" : "spa" : "custom",
1488
1503
  ssr: {
1489
1504
  external: serverEnvironment.resolve?.external,
1490
1505
  resolve: serverEnvironment.resolve
@@ -1717,6 +1732,21 @@ const reactRouterVitePlugin = () => {
1717
1732
  previewServer.middlewares.use(async (req, res, next) => {
1718
1733
  if (!ctx.reactRouterConfig.ssr && (!process.env.hasOwnProperty("IS_RR_BUILD_REQUEST") ? true : process.env.IS_RR_BUILD_REQUEST !== "yes")) return next();
1719
1734
  try {
1735
+ if (isApiOnlyMode(ctx.reactRouterConfig) && process.env.IS_RR_BUILD_REQUEST !== "yes") {
1736
+ let { basename, routeDiscovery } = ctx.reactRouterConfig;
1737
+ let manifestPath = routeDiscovery?.mode === "lazy" ? path$2.posix.join(basename, routeDiscovery.manifestPath ?? "/__manifest") : void 0;
1738
+ let pathname = new URL(req.originalUrl ?? req.url ?? "/", "http://localhost").pathname;
1739
+ if (!pathname.endsWith(".data") && pathname !== manifestPath) {
1740
+ let clientBuildDirectory = getClientBuildDirectory$1(ctx.reactRouterConfig);
1741
+ let previewPathname = decodeURIComponent(new URL(req.url ?? "/", "http://localhost").pathname);
1742
+ if (previewPathname.endsWith(".html") && existsSync(path$2.join(clientBuildDirectory, previewPathname))) return next();
1743
+ let fallbackFile = path$2.join(clientBuildDirectory, "__spa-fallback.html");
1744
+ if (!existsSync(fallbackFile)) fallbackFile = path$2.join(clientBuildDirectory, "index.html");
1745
+ res.setHeader("Content-Type", "text/html; charset=utf-8");
1746
+ res.end(await readFile(fallbackFile));
1747
+ return;
1748
+ }
1749
+ }
1720
1750
  let handler = await getHandler();
1721
1751
  let request = await fromNodeRequest(req, res);
1722
1752
  await sendResponse(res, await handler(request, await reactRouterDevLoadContext(request)));
@@ -1817,11 +1847,14 @@ const reactRouterVitePlugin = () => {
1817
1847
  let routeFileName = path$2.basename(routeModuleId);
1818
1848
  let sourceExports = await getRouteModuleExports(viteChildCompiler, ctx, routeModuleId);
1819
1849
  let { chunkedExports = [] } = options?.ssr ? {} : await detectRouteChunksIfEnabled(cache, ctx, id, code);
1820
- return `export { ${sourceExports.filter((exportName) => {
1821
- let isRouteEntryExport = options?.ssr && SERVER_ONLY_ROUTE_EXPORTS.includes(exportName) || CLIENT_ROUTE_EXPORTS$1.includes(exportName);
1822
- let isChunkedExport = chunkedExports.includes(exportName);
1823
- return isRouteEntryExport && !isChunkedExport;
1824
- }).join(", ")} } from "./${routeFileName}";`;
1850
+ return {
1851
+ code: `export { ${sourceExports.filter((exportName) => {
1852
+ let isRouteEntryExport = options?.ssr && SERVER_ONLY_ROUTE_EXPORTS.includes(exportName) || CLIENT_ROUTE_EXPORTS$1.includes(exportName);
1853
+ let isChunkedExport = chunkedExports.includes(exportName);
1854
+ return isRouteEntryExport && !isChunkedExport;
1855
+ }).join(", ")} } from "./${routeFileName}";`,
1856
+ map: { mappings: "" }
1857
+ };
1825
1858
  }
1826
1859
  },
1827
1860
  {
@@ -1946,7 +1979,8 @@ const reactRouterVitePlugin = () => {
1946
1979
  if (isRouteChunkModuleId(id)) id = id.split("?")[0];
1947
1980
  let route = getRoute(ctx.reactRouterConfig, id);
1948
1981
  if (!route) return;
1949
- if (!options?.ssr && isSpaModeEnabled(ctx.reactRouterConfig)) {
1982
+ let isServerEnvironment = isReactRouterServerEnvironment(ctx, this.environment.name);
1983
+ if (!options?.ssr && isSpaModeEnabled(ctx.reactRouterConfig) && !isApiOnlyMode(ctx.reactRouterConfig)) {
1950
1984
  let exportNames = getExportNames(code);
1951
1985
  let serverOnlyExports = exportNames.filter((exp) => {
1952
1986
  if (route.id === "root" && exp === "loader") return false;
@@ -1967,6 +2001,7 @@ const reactRouterVitePlugin = () => {
1967
2001
  let [filepath] = id.split("?");
1968
2002
  let ast = parse$1(code, { sourceType: "module" });
1969
2003
  if (!options?.ssr) removeExports(ast, SERVER_ONLY_ROUTE_EXPORTS);
2004
+ else if (isApiOnlyMode(ctx.reactRouterConfig) && isServerEnvironment && !isPrerenderingEnabled(ctx.reactRouterConfig) && viteCommand === "build" && route.id !== "root") removeExports(ast, CLIENT_ROUTE_EXPORTS$1);
1970
2005
  decorateComponentExportsWithProps(ast);
1971
2006
  return generate(ast, {
1972
2007
  sourceMaps: true,
@@ -2108,7 +2143,7 @@ const reactRouterVitePlugin = () => {
2108
2143
  else requests.push(createRouteRequest(prerenderPath, reactRouterConfig));
2109
2144
  }
2110
2145
  }
2111
- if (!ctx.reactRouterConfig.ssr) requests.push(createSpaModeRequest(ctx.reactRouterConfig));
2146
+ if (!ctx.reactRouterConfig.ssr || ctx.reactRouterConfig.ssr === "unstable_api-only") requests.push(createSpaModeRequest(ctx.reactRouterConfig));
2112
2147
  return requests;
2113
2148
  },
2114
2149
  async postProcess(request, response, metadata) {
@@ -2175,7 +2210,7 @@ const reactRouterVitePlugin = () => {
2175
2210
  async finalize(buildDirectory) {
2176
2211
  invariant(viteConfig);
2177
2212
  let { ssr } = ctx.reactRouterConfig;
2178
- if (!ssr) {
2213
+ if (!ssr || ssr === "unstable_api-only") {
2179
2214
  let spaFallback = path$2.join(buildDirectory, "__spa-fallback.html");
2180
2215
  let index = path$2.join(buildDirectory, "index.html");
2181
2216
  let finalSpaPath;
@@ -2310,7 +2345,10 @@ function isPrerenderingEnabled(reactRouterConfig) {
2310
2345
  return reactRouterConfig.prerender != null && reactRouterConfig.prerender !== false;
2311
2346
  }
2312
2347
  function isSpaModeEnabled(reactRouterConfig) {
2313
- return reactRouterConfig.ssr === false && !isPrerenderingEnabled(reactRouterConfig);
2348
+ return (!reactRouterConfig.ssr || reactRouterConfig.ssr === "unstable_api-only") && !isPrerenderingEnabled(reactRouterConfig);
2349
+ }
2350
+ function isApiOnlyMode(reactRouterConfig) {
2351
+ return reactRouterConfig.ssr === "unstable_api-only";
2314
2352
  }
2315
2353
  function getStaticPrerenderPaths(routes) {
2316
2354
  let paths = ["/"];
@@ -2476,7 +2514,10 @@ async function detectRouteChunksIfEnabled(cache, ctx, id, input) {
2476
2514
  }
2477
2515
  async function getRouteChunkIfEnabled(cache, ctx, id, chunkName, input) {
2478
2516
  if (!ctx.reactRouterConfig.splitRouteModules) return null;
2479
- return getRouteChunkCode(await resolveRouteFileCode(ctx, input), chunkName, cache, normalizeRelativeFilePath(id, ctx.reactRouterConfig) + (typeof input === "string" ? "" : "?read"));
2517
+ return getRouteChunkCode(await resolveRouteFileCode(ctx, input), chunkName, cache, normalizeRelativeFilePath(id, ctx.reactRouterConfig) + (typeof input === "string" ? "" : "?read"), {
2518
+ sourceMaps: true,
2519
+ sourceFileName: path$2.basename(id.split("?")[0])
2520
+ });
2480
2521
  }
2481
2522
  function validateRouteChunks$1({ ctx, id, valid }) {
2482
2523
  if (isRootRouteModuleId(ctx, id)) return;
@@ -2665,7 +2706,7 @@ function createDataRequest(prerenderPath, reactRouterConfig, onlyRoutes, isResou
2665
2706
  let url = new URL(`http://localhost${normalizedPath}`);
2666
2707
  if (onlyRoutes?.length) url.searchParams.set("_routes", onlyRoutes.join(","));
2667
2708
  return {
2668
- request: new Request(url),
2709
+ request: new Request(url, { headers: { "X-React-Router-Prerender": "yes" } }),
2669
2710
  metadata: {
2670
2711
  type: "data",
2671
2712
  path: prerenderPath,
@@ -2675,7 +2716,7 @@ function createDataRequest(prerenderPath, reactRouterConfig, onlyRoutes, isResou
2675
2716
  }
2676
2717
  function createRouteRequest(prerenderPath, reactRouterConfig, data) {
2677
2718
  let normalizedPath = `${reactRouterConfig.basename}${prerenderPath}/`.replace(/\/\/+/g, "/");
2678
- let headers = new Headers();
2719
+ let headers = new Headers({ "X-React-Router-Prerender": "yes" });
2679
2720
  if (data) {
2680
2721
  let encodedData = encodeURI(data);
2681
2722
  if (encodedData.length < 8 * 1024) headers.set("X-React-Router-Prerender-Data", encodedData);
@@ -2690,8 +2731,13 @@ function createRouteRequest(prerenderPath, reactRouterConfig, data) {
2690
2731
  }
2691
2732
  function createResourceRouteRequest(prerenderPath, reactRouterConfig, requestInit) {
2692
2733
  let normalizedPath = `${reactRouterConfig.basename}${prerenderPath}/`.replace(/\/\/+/g, "/").replace(/\/$/g, "");
2734
+ let headers = new Headers(requestInit?.headers);
2735
+ headers.set("X-React-Router-Prerender", "yes");
2693
2736
  return {
2694
- request: new Request(`http://localhost${normalizedPath}`, requestInit),
2737
+ request: new Request(`http://localhost${normalizedPath}`, {
2738
+ ...requestInit,
2739
+ headers
2740
+ }),
2695
2741
  metadata: {
2696
2742
  type: "resource",
2697
2743
  path: prerenderPath
@@ -2851,6 +2897,38 @@ const ENSURE_CLIENT_ROUTE_MODULE_CHUNK_FOR_HMR = `
2851
2897
  import * as ___EnsureClientRouteModuleForHMR_REACT___ from "react";
2852
2898
  export function EnsureClientRouteModuleForHMR___() { return ___EnsureClientRouteModuleForHMR_REACT___.createElement(___EnsureClientRouteModuleForHMR_REACT___.Fragment, null) }
2853
2899
  `;
2900
+ function createEmptySourceMap() {
2901
+ return {
2902
+ version: 3,
2903
+ names: [],
2904
+ sources: [],
2905
+ mappings: ""
2906
+ };
2907
+ }
2908
+ function generateRouteModule(code, map, filename) {
2909
+ const ast = parse$1(code, { sourceType: "module" });
2910
+ const generatorOptions = {
2911
+ sourceMaps: true,
2912
+ sourceFileName: filename,
2913
+ inputSourceMap: map
2914
+ };
2915
+ return {
2916
+ ast,
2917
+ generate: () => generate(ast, generatorOptions)
2918
+ };
2919
+ }
2920
+ function prependUnmappedCode(prefix, generated) {
2921
+ if (generated.map) generated.map.mappings = ";".repeat(prefix.match(/\n/g)?.length ?? 0) + generated.map.mappings;
2922
+ return {
2923
+ code: prefix + generated.code,
2924
+ map: generated.map
2925
+ };
2926
+ }
2927
+ function appendUnmappedCode(generated, code) {
2928
+ if (!generated.code.endsWith("\n") && !code.startsWith("\n")) code = "\n" + code;
2929
+ if (generated.map) generated.map.mappings += ";A".repeat(code.match(/\n/g)?.length ?? 0);
2930
+ generated.code += code;
2931
+ }
2854
2932
  function virtualRouteModulesPlugin({ enforceSplitRouteModules, environments: { client = ["client", "ssr"], server = ["rsc"] } = {}, getRouteIdForFile, isRootRouteModule, transformToJs, shouldTransform }) {
2855
2933
  let clientEnvironments = new Set(client);
2856
2934
  let serverEnvironments = new Set(server);
@@ -2886,7 +2964,10 @@ function virtualRouteModulesPlugin({ enforceSplitRouteModules, environments: { c
2886
2964
  }
2887
2965
  });
2888
2966
  }
2889
- return { code: "\"use client\";\n" + result };
2967
+ return {
2968
+ code: "\"use client\";\n" + result,
2969
+ map: createEmptySourceMap()
2970
+ };
2890
2971
  }
2891
2972
  async function createServerRouteEntry(id, code, isRootRouteModule, routeId) {
2892
2973
  let result = "";
@@ -2926,16 +3007,19 @@ ${result}`;
2926
3007
  }
2927
3008
  });
2928
3009
  }
2929
- return { code: result };
3010
+ return {
3011
+ code: result,
3012
+ map: createEmptySourceMap()
3013
+ };
2930
3014
  }
2931
- function createServerRouteModule(code) {
2932
- const ast = parse$1(code, { sourceType: "module" });
3015
+ function createServerRouteModule(code, map, filename) {
3016
+ const { ast, generate } = generateRouteModule(code, map, filename);
2933
3017
  removeExports(ast, CLIENT_ROUTE_EXPORTS);
2934
- return generate(ast);
3018
+ return generate();
2935
3019
  }
2936
- async function createClientRouteModuleChunk(id, code, chunk, routeId, isRootRouteModule, isDevMode) {
3020
+ async function createClientRouteModuleChunk(id, code, chunk, routeId, isRootRouteModule, isDevMode, map, filename) {
2937
3021
  let routeChunks = detectRouteChunks(cache, id, code, isRootRouteModule);
2938
- const ast = parse$1(code, { sourceType: "module" });
3022
+ const { ast, generate } = generateRouteModule(code, map, filename);
2939
3023
  const { staticExports } = await parseRouteExports(code);
2940
3024
  if (chunk === "shared") removeExports(ast, [...SERVER_ROUTE_EXPORTS, ...routeChunks.chunkedExports]);
2941
3025
  else {
@@ -2943,33 +3027,26 @@ ${result}`;
2943
3027
  toRemove.delete(chunk);
2944
3028
  removeExports(ast, Array.from(toRemove));
2945
3029
  }
2946
- let result = "\"use client\";\n" + generate(ast).code;
3030
+ let result = prependUnmappedCode("\"use client\";\n", generate());
2947
3031
  if (chunk === "shared") {
2948
- if (isRootRouteModule && !staticExports.includes("ErrorBoundary") && !staticExports.includes("ServerErrorBoundary")) {
2949
- const hasRootLayout = staticExports.includes("Layout") || staticExports.includes("ServerLayout");
2950
- result += `\nimport { createElement as __rr_createElement } from "react";\n`;
2951
- result += `import { UNSAFE_RSCDefaultRootErrorBoundary } from "react-router";\n`;
2952
- result += `export function ErrorBoundary() {\n`;
2953
- result += ` return __rr_createElement(UNSAFE_RSCDefaultRootErrorBoundary, { hasRootLayout: ${hasRootLayout} });\n`;
2954
- result += `}\n`;
2955
- }
2956
- result += ENSURE_CLIENT_ROUTE_MODULE_CHUNK_FOR_HMR;
3032
+ if (isRootRouteModule && !staticExports.includes("ErrorBoundary") && !staticExports.includes("ServerErrorBoundary")) appendUnmappedCode(result, `
3033
+ import { createElement as __rr_createElement } from "react";
3034
+ import { UNSAFE_RSCDefaultRootErrorBoundary } from "react-router";
3035
+ export function ErrorBoundary() {
3036
+ return __rr_createElement(UNSAFE_RSCDefaultRootErrorBoundary, { hasRootLayout: ${staticExports.includes("Layout") || staticExports.includes("ServerLayout")} });\n}\n`);
3037
+ appendUnmappedCode(result, ENSURE_CLIENT_ROUTE_MODULE_CHUNK_FOR_HMR);
2957
3038
  }
2958
3039
  let hasAction = staticExports.includes("action");
2959
3040
  let hasLoader = staticExports.includes("loader");
2960
3041
  let hasComponent = staticExports.includes("default") || staticExports.includes("ServerComponent");
2961
3042
  let hasErrorBoundary = staticExports.includes("ErrorBoundary") || staticExports.includes("ServerErrorBoundary");
2962
- if (isDevMode) {
2963
- result += `export function ReactRouterHMRMeta___() {return null;};\n`;
2964
- result += `Object.assign(ReactRouterHMRMeta___, {
3043
+ if (isDevMode) appendUnmappedCode(result, `export function ReactRouterHMRMeta___() {return null;};\nObject.assign(ReactRouterHMRMeta___, {
2965
3044
  hasAction: ${JSON.stringify(hasAction)},
2966
3045
  hasComponent: ${JSON.stringify(hasComponent)},
2967
3046
  hasErrorBoundary: ${JSON.stringify(hasErrorBoundary)},
2968
3047
  hasLoader: ${JSON.stringify(hasLoader)},
2969
3048
  hasClientLoader: ${JSON.stringify(staticExports.includes("clientLoader"))},
2970
- });\n`;
2971
- result += `\nif (import.meta.hot) {\n`;
2972
- result += ` import.meta.hot.accept((mod) => {
3049
+ });\n\nif (import.meta.hot) {\n import.meta.hot.accept((mod) => {
2973
3050
  if (typeof __reactRouterDataRouter === "object") {
2974
3051
  __reactRouterDataRouter._updateRoutesForHMR(new Map([[${JSON.stringify(routeId)}, {
2975
3052
  routeModule: mod,
@@ -2983,10 +3060,8 @@ ${result}`;
2983
3060
  }
2984
3061
  }
2985
3062
  });
2986
- `;
2987
- result += `}\n`;
2988
- }
2989
- return { code: result };
3063
+ }\n`);
3064
+ return result;
2990
3065
  }
2991
3066
  return {
2992
3067
  name: "react-router-rsc-virtual-route-modules",
@@ -2998,12 +3073,13 @@ ${result}`;
2998
3073
  let isClientEnvironment = clientEnvironments.has(this.environment.name);
2999
3074
  let isServerEnvironment = serverEnvironments.has(this.environment.name);
3000
3075
  if (!isClientEnvironment && !isServerEnvironment) return;
3001
- let code = await transformToJs(_code, filename);
3076
+ let transformed = await transformToJs(_code, filename);
3077
+ let code = transformed.code;
3002
3078
  let searchParams = rest.length > 0 ? new URLSearchParams(rest.join("?")) : null;
3003
3079
  let clientRouteModuleType = searchParams?.get("client-route-module");
3004
3080
  let isServerRouteModule = searchParams?.has("server-route-module");
3005
- if (clientRouteModuleType) return await createClientRouteModuleChunk(id, code, clientRouteModuleType, routeId, isRootRouteModule(filename), this.environment.mode === "dev");
3006
- if (isServerRouteModule) return createServerRouteModule(code);
3081
+ if (clientRouteModuleType) return await createClientRouteModuleChunk(id, code, clientRouteModuleType, routeId, isRootRouteModule(filename), this.environment.mode === "dev", transformed.map, filename);
3082
+ if (isServerRouteModule) return createServerRouteModule(code, transformed.map, filename);
3007
3083
  if (isClientEnvironment) return await createClientRouteEntry(id, code, isRootRouteModule(filename), routeId);
3008
3084
  return await createServerRouteEntry(id, code, isRootRouteModule(filename), routeId);
3009
3085
  }
@@ -3169,7 +3245,7 @@ function reactRouterRSCVitePlugin() {
3169
3245
  await preloadVite();
3170
3246
  let vite = getVite();
3171
3247
  let lang = getTransformLanguage(filename);
3172
- return ("transformWithOxc" in vite && typeof vite.transformWithOxc === "function" ? await vite.transformWithOxc(code, filename, {
3248
+ return "transformWithOxc" in vite && typeof vite.transformWithOxc === "function" ? await vite.transformWithOxc(code, filename, {
3173
3249
  lang,
3174
3250
  jsx: {
3175
3251
  runtime: "automatic",
@@ -3182,7 +3258,7 @@ function reactRouterRSCVitePlugin() {
3182
3258
  format: "esm",
3183
3259
  jsx: "automatic",
3184
3260
  jsxDev: viteCommand !== "build"
3185
- })).code;
3261
+ });
3186
3262
  }
3187
3263
  async function getClientVersion(source) {
3188
3264
  const digest = await globalThis.crypto.subtle.digest("SHA-256", new TextEncoder().encode(source));
@@ -3211,6 +3287,7 @@ function reactRouterRSCVitePlugin() {
3211
3287
  if (userConfig.buildEnd) errors.push("buildEnd");
3212
3288
  if (userConfig.presets?.length) errors.push("presets");
3213
3289
  if (userConfig.serverBundles) errors.push("serverBundles");
3290
+ if (userConfig.ssr === "unstable_api-only") errors.push("ssr: \"unstable_api-only\"");
3214
3291
  if (errors.length) return `RSC Framework Mode does not currently support the following React Router config:\n${errors.map((x) => ` - ${x}`).join("\n")}\n`;
3215
3292
  }
3216
3293
  });
@@ -3642,7 +3719,7 @@ function createRSCOptimizeDepsRouteModulesPlugin({ routeFiles, transformToJs })
3642
3719
  let normalizedFilename = getVite().normalizePath(filename);
3643
3720
  if (!routeFiles.has(normalizedFilename)) return;
3644
3721
  return {
3645
- code: createClientRouteModuleForOptimizeDepsScan(await transformToJs(code, filename)).code,
3722
+ code: createClientRouteModuleForOptimizeDepsScan((await transformToJs(code, filename)).code).code,
3646
3723
  map: null,
3647
3724
  moduleType: "js"
3648
3725
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@react-router/dev",
3
3
  "type": "module",
4
- "version": "8.3.1",
4
+ "version": "8.5.0",
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.3.1"
110
+ "@react-router/node": "8.5.0"
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/serve": "8.3.1",
136
- "react-router": "^8.3.1"
135
+ "react-router": "^8.5.0",
136
+ "@react-router/serve": "8.5.0"
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.3.1",
145
- "react-router": "^8.3.1"
144
+ "@react-router/serve": "^8.5.0",
145
+ "react-router": "^8.5.0"
146
146
  },
147
147
  "peerDependenciesMeta": {
148
148
  "@vitejs/plugin-rsc": {