@react-router/dev 7.9.4 → 7.9.5-pre.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,18 @@
1
1
  # `@react-router/dev`
2
2
 
3
+ ## 7.9.5-pre.0
4
+
5
+ ### Patch Changes
6
+
7
+ - Introduce a `prerender.unstable_concurrency` option, to support running the prerendering concurrently, potentially speeding up the build. ([#14380](https://github.com/remix-run/react-router/pull/14380))
8
+ - Move RSCHydratedRouter and utils to `/dom` export. ([#14457](https://github.com/remix-run/react-router/pull/14457))
9
+ - Ensure route navigation doesn't remove CSS `link` elements used by dynamic imports ([#14463](https://github.com/remix-run/react-router/pull/14463))
10
+ - Typegen: only register route module types for routes within the app directory ([#14439](https://github.com/remix-run/react-router/pull/14439))
11
+ - Updated dependencies:
12
+ - `react-router@7.9.5-pre.0`
13
+ - `@react-router/node@7.9.5-pre.0`
14
+ - `@react-router/serve@7.9.5-pre.0`
15
+
3
16
  ## 7.9.4
4
17
 
5
18
  ### Patch Changes
@@ -156,7 +169,6 @@
156
169
  - Stabilize middleware and context APIs. ([#14215](https://github.com/remix-run/react-router/pull/14215))
157
170
 
158
171
  We have removed the `unstable_` prefix from the following APIs and they are now considered stable and ready for production use:
159
-
160
172
  - [`RouterContextProvider`](https://reactrouter.com/api/utils/RouterContextProvider)
161
173
  - [`createContext`](https://reactrouter.com/api/utils/createContext)
162
174
  - `createBrowserRouter` [`getContext`](https://reactrouter.com/api/data-routers/createBrowserRouter#optsgetcontext) option
@@ -899,7 +911,6 @@
899
911
  ```
900
912
 
901
913
  This initial implementation targets type inference for:
902
-
903
914
  - `Params` : Path parameters from your routing config in `routes.ts` including file-based routing
904
915
  - `LoaderData` : Loader data from `loader` and/or `clientLoader` within your route module
905
916
  - `ActionData` : Action data from `action` and/or `clientAction` within your route module
@@ -914,7 +925,6 @@
914
925
  ```
915
926
 
916
927
  Check out our docs for more:
917
-
918
928
  - [_Explanations > Type Safety_](https://reactrouter.com/dev/guides/explanation/type-safety)
919
929
  - [_How-To > Setting up type safety_](https://reactrouter.com/dev/guides/how-to/setting-up-type-safety)
920
930
 
@@ -1114,7 +1124,6 @@
1114
1124
  - Vite: Provide `Unstable_ServerBundlesFunction` and `Unstable_VitePluginConfig` types ([#8654](https://github.com/remix-run/remix/pull/8654))
1115
1125
 
1116
1126
  - Vite: add `--sourcemapClient` and `--sourcemapServer` flags to `remix vite:build` ([#8613](https://github.com/remix-run/remix/pull/8613))
1117
-
1118
1127
  - `--sourcemapClient`
1119
1128
 
1120
1129
  - `--sourcemapClient=inline`
@@ -1451,7 +1460,6 @@
1451
1460
  - Add support for `clientLoader`/`clientAction`/`HydrateFallback` route exports ([RFC](https://github.com/remix-run/remix/discussions/7634)) ([#8173](https://github.com/remix-run/remix/pull/8173))
1452
1461
 
1453
1462
  Remix now supports loaders/actions that run on the client (in addition to, or instead of the loader/action that runs on the server). While we still recommend server loaders/actions for the majority of your data needs in a Remix app - these provide some levers you can pull for more advanced use-cases such as:
1454
-
1455
1463
  - Leveraging a data source local to the browser (i.e., `localStorage`)
1456
1464
  - Managing a client-side cache of server data (like `IndexedDB`)
1457
1465
  - Bypassing the Remix server in a BFF setup and hitting your API directly from the browser
@@ -1855,7 +1863,6 @@
1855
1863
  - Output esbuild metafiles for bundle analysis ([#6772](https://github.com/remix-run/remix/pull/6772))
1856
1864
 
1857
1865
  Written to server build directory (`build/` by default):
1858
-
1859
1866
  - `metafile.css.json`
1860
1867
  - `metafile.js.json` (browser JS)
1861
1868
  - `metafile.server.json` (server JS)
@@ -1953,7 +1960,6 @@
1953
1960
  - built-in tls support ([#6483](https://github.com/remix-run/remix/pull/6483))
1954
1961
 
1955
1962
  New options:
1956
-
1957
1963
  - `--tls-key` / `tlsKey`: TLS key
1958
1964
  - `--tls-cert` / `tlsCert`: TLS Certificate
1959
1965
 
@@ -2224,7 +2230,6 @@
2224
2230
  ```
2225
2231
 
2226
2232
  The dev server will:
2227
-
2228
2233
  - force `NODE_ENV=development` and warn you if it was previously set to something else
2229
2234
  - rebuild your app whenever your Remix app code changes
2230
2235
  - restart your app server whenever rebuilds succeed
package/dist/cli/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * @react-router/dev v7.9.4
3
+ * @react-router/dev v7.9.5-pre.0
4
4
  *
5
5
  * Copyright (c) Remix Software Inc.
6
6
  *
@@ -390,11 +390,20 @@ async function resolveConfig({
390
390
  if (!ssr && serverBundles) {
391
391
  serverBundles = void 0;
392
392
  }
393
- let isValidPrerenderConfig = prerender == null || typeof prerender === "boolean" || Array.isArray(prerender) || typeof prerender === "function";
394
- if (!isValidPrerenderConfig) {
395
- return err(
396
- "The `prerender` config must be a boolean, an array of string paths, or a function returning a boolean or array of string paths"
397
- );
393
+ if (prerender) {
394
+ let isValidPrerenderPathsConfig = (p) => typeof p === "boolean" || typeof p === "function" || Array.isArray(p);
395
+ let isValidPrerenderConfig = isValidPrerenderPathsConfig(prerender) || typeof prerender === "object" && "paths" in prerender && isValidPrerenderPathsConfig(prerender.paths);
396
+ if (!isValidPrerenderConfig) {
397
+ return err(
398
+ "The `prerender`/`prerender.paths` config must be a boolean, an array of string paths, or a function returning a boolean or array of string paths."
399
+ );
400
+ }
401
+ let isValidConcurrencyConfig = typeof prerender != "object" || !("unstable_concurrency" in prerender) || typeof prerender.unstable_concurrency === "number" && Number.isInteger(prerender.unstable_concurrency) && prerender.unstable_concurrency > 0;
402
+ if (!isValidConcurrencyConfig) {
403
+ return err(
404
+ "The `prerender.unstable_concurrency` config must be a positive integer if specified."
405
+ );
406
+ }
398
407
  }
399
408
  let routeDiscovery;
400
409
  if (userRouteDiscovery == null) {
@@ -1061,13 +1070,13 @@ function routeModulesType(ctx) {
1061
1070
  (route) => t2.tsPropertySignature(
1062
1071
  t2.stringLiteral(route.id),
1063
1072
  t2.tsTypeAnnotation(
1064
- t2.tsTypeQuery(
1073
+ isInAppDirectory(ctx, route.file) ? t2.tsTypeQuery(
1065
1074
  t2.tsImportType(
1066
1075
  t2.stringLiteral(
1067
1076
  `./${Path3.relative(ctx.rootDirectory, ctx.config.appDirectory)}/${route.file}`
1068
1077
  )
1069
1078
  )
1070
- )
1079
+ ) : t2.tsUnknownKeyword()
1071
1080
  )
1072
1081
  )
1073
1082
  )
@@ -1771,7 +1780,7 @@ function resolveEnvironmentsOptions(environmentResolvers, resolverOptions) {
1771
1780
  function isNonNullable(x) {
1772
1781
  return x != null;
1773
1782
  }
1774
- var import_node_crypto, import_node_fs3, import_promises2, path7, url, babel2, import_node_fetch_server2, import_react_router2, import_es_module_lexer, import_pick3, import_jsesc, import_picocolors5, import_kebabCase, CLIENT_NON_COMPONENT_EXPORTS, CLIENT_ROUTE_EXPORTS, BUILD_CLIENT_ROUTE_QUERY_STRING, SSR_BUNDLE_PREFIX, virtualHmrRuntime, virtualInjectHmrRuntime, virtual, getServerBuildDirectory, getClientBuildDirectory, defaultEntriesDir, defaultEntries, REACT_REFRESH_HEADER;
1783
+ var import_node_crypto, import_node_fs3, import_promises2, path7, url, babel2, import_node_fetch_server2, import_react_router2, import_es_module_lexer, import_pick3, import_jsesc, import_picocolors5, import_kebabCase, import_p_map, CLIENT_NON_COMPONENT_EXPORTS, CLIENT_ROUTE_EXPORTS, BUILD_CLIENT_ROUTE_QUERY_STRING, SSR_BUNDLE_PREFIX, virtualHmrRuntime, virtualInjectHmrRuntime, virtual, getServerBuildDirectory, getClientBuildDirectory, defaultEntriesDir, defaultEntries, REACT_REFRESH_HEADER;
1775
1784
  var init_plugin = __esm({
1776
1785
  "vite/plugin.ts"() {
1777
1786
  "use strict";
@@ -1788,6 +1797,7 @@ var init_plugin = __esm({
1788
1797
  import_jsesc = __toESM(require("jsesc"));
1789
1798
  import_picocolors5 = __toESM(require("picocolors"));
1790
1799
  import_kebabCase = __toESM(require("lodash/kebabCase"));
1800
+ import_p_map = __toESM(require("p-map"));
1791
1801
  init_typegen();
1792
1802
  init_invariant();
1793
1803
  init_babel();
@@ -12,8 +12,8 @@ import {
12
12
  unstable_createCallServer as createCallServer,
13
13
  unstable_getRSCStream as getRSCStream,
14
14
  unstable_RSCHydratedRouter as RSCHydratedRouter,
15
- } from "react-router";
16
- import type { unstable_RSCPayload as RSCPayload } from "react-router";
15
+ type unstable_RSCPayload as RSCPayload,
16
+ } from "react-router/dom";
17
17
 
18
18
  setServerCallback(
19
19
  createCallServer({
package/dist/config.d.ts CHANGED
@@ -58,6 +58,9 @@ type BuildEndHook = (args: {
58
58
  reactRouterConfig: ResolvedReactRouterConfig;
59
59
  viteConfig: Vite.ResolvedConfig;
60
60
  }) => void | Promise<void>;
61
+ type PrerenderPaths = boolean | Array<string> | ((args: {
62
+ getStaticPaths: () => string[];
63
+ }) => Array<string> | Promise<Array<string>>);
61
64
  /**
62
65
  * Config to be exported via the default export from `react-router.config.ts`.
63
66
  */
@@ -93,10 +96,17 @@ type ReactRouterConfig = {
93
96
  /**
94
97
  * An array of URLs to prerender to HTML files at build time. Can also be a
95
98
  * function returning an array to dynamically generate URLs.
96
- */
97
- prerender?: boolean | Array<string> | ((args: {
98
- getStaticPaths: () => string[];
99
- }) => Array<string> | Promise<Array<string>>);
99
+ *
100
+ * `unstable_concurrency` defaults to 1, which means "no concurrency" - fully serial execution.
101
+ * Setting it to a value more than 1 enables concurrent prerendering.
102
+ * Setting it to a value higher than one can increase the speed of the build,
103
+ * but may consume more resources, and send more concurrent requests to the
104
+ * server/CMS.
105
+ */
106
+ prerender?: PrerenderPaths | {
107
+ paths: PrerenderPaths;
108
+ unstable_concurrency?: number;
109
+ };
100
110
  /**
101
111
  * An array of React Router plugin config presets to ease integration with
102
112
  * other platforms and tools.
package/dist/config.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @react-router/dev v7.9.4
2
+ * @react-router/dev v7.9.5-pre.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 v7.9.4
2
+ * @react-router/dev v7.9.5-pre.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @react-router/dev v7.9.4
2
+ * @react-router/dev v7.9.5-pre.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -420,11 +420,20 @@ async function resolveConfig({
420
420
  if (!ssr && serverBundles) {
421
421
  serverBundles = void 0;
422
422
  }
423
- let isValidPrerenderConfig = prerender == null || typeof prerender === "boolean" || Array.isArray(prerender) || typeof prerender === "function";
424
- if (!isValidPrerenderConfig) {
425
- return err(
426
- "The `prerender` config must be a boolean, an array of string paths, or a function returning a boolean or array of string paths"
427
- );
423
+ if (prerender) {
424
+ let isValidPrerenderPathsConfig = (p) => typeof p === "boolean" || typeof p === "function" || Array.isArray(p);
425
+ let isValidPrerenderConfig = isValidPrerenderPathsConfig(prerender) || typeof prerender === "object" && "paths" in prerender && isValidPrerenderPathsConfig(prerender.paths);
426
+ if (!isValidPrerenderConfig) {
427
+ return err(
428
+ "The `prerender`/`prerender.paths` config must be a boolean, an array of string paths, or a function returning a boolean or array of string paths."
429
+ );
430
+ }
431
+ let isValidConcurrencyConfig = typeof prerender != "object" || !("unstable_concurrency" in prerender) || typeof prerender.unstable_concurrency === "number" && Number.isInteger(prerender.unstable_concurrency) && prerender.unstable_concurrency > 0;
432
+ if (!isValidConcurrencyConfig) {
433
+ return err(
434
+ "The `prerender.unstable_concurrency` config must be a positive integer if specified."
435
+ );
436
+ }
428
437
  }
429
438
  let routeDiscovery;
430
439
  if (userRouteDiscovery == null) {
package/dist/vite.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @react-router/dev v7.9.4
2
+ * @react-router/dev v7.9.5-pre.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -59,6 +59,7 @@ var import_pick3 = __toESM(require("lodash/pick"));
59
59
  var import_jsesc = __toESM(require("jsesc"));
60
60
  var import_picocolors4 = __toESM(require("picocolors"));
61
61
  var import_kebabCase = __toESM(require("lodash/kebabCase"));
62
+ var import_p_map = __toESM(require("p-map"));
62
63
 
63
64
  // typegen/index.ts
64
65
  var import_promises = __toESM(require("fs/promises"));
@@ -447,11 +448,20 @@ async function resolveConfig({
447
448
  if (!ssr && serverBundles) {
448
449
  serverBundles = void 0;
449
450
  }
450
- let isValidPrerenderConfig = prerender == null || typeof prerender === "boolean" || Array.isArray(prerender) || typeof prerender === "function";
451
- if (!isValidPrerenderConfig) {
452
- return err(
453
- "The `prerender` config must be a boolean, an array of string paths, or a function returning a boolean or array of string paths"
454
- );
451
+ if (prerender) {
452
+ let isValidPrerenderPathsConfig = (p) => typeof p === "boolean" || typeof p === "function" || Array.isArray(p);
453
+ let isValidPrerenderConfig = isValidPrerenderPathsConfig(prerender) || typeof prerender === "object" && "paths" in prerender && isValidPrerenderPathsConfig(prerender.paths);
454
+ if (!isValidPrerenderConfig) {
455
+ return err(
456
+ "The `prerender`/`prerender.paths` config must be a boolean, an array of string paths, or a function returning a boolean or array of string paths."
457
+ );
458
+ }
459
+ let isValidConcurrencyConfig = typeof prerender != "object" || !("unstable_concurrency" in prerender) || typeof prerender.unstable_concurrency === "number" && Number.isInteger(prerender.unstable_concurrency) && prerender.unstable_concurrency > 0;
460
+ if (!isValidConcurrencyConfig) {
461
+ return err(
462
+ "The `prerender.unstable_concurrency` config must be a positive integer if specified."
463
+ );
464
+ }
455
465
  }
456
466
  let routeDiscovery;
457
467
  if (userRouteDiscovery == null) {
@@ -1049,13 +1059,13 @@ function routeModulesType(ctx) {
1049
1059
  (route) => t2.tsPropertySignature(
1050
1060
  t2.stringLiteral(route.id),
1051
1061
  t2.tsTypeAnnotation(
1052
- t2.tsTypeQuery(
1062
+ isInAppDirectory(ctx, route.file) ? t2.tsTypeQuery(
1053
1063
  t2.tsImportType(
1054
1064
  t2.stringLiteral(
1055
1065
  `./${Path3.relative(ctx.rootDirectory, ctx.config.appDirectory)}/${route.file}`
1056
1066
  )
1057
1067
  )
1058
- )
1068
+ ) : t2.tsUnknownKeyword()
1059
1069
  )
1060
1070
  )
1061
1071
  )
@@ -2549,7 +2559,7 @@ var getClientEntryChunk = (ctx, viteManifest) => {
2549
2559
  invariant(chunk, `Chunk not found: ${filePath}`);
2550
2560
  return chunk;
2551
2561
  };
2552
- var getReactRouterManifestBuildAssets = (ctx, viteConfig, viteManifest, entryFilePath, route) => {
2562
+ var getReactRouterManifestBuildAssets = (ctx, viteConfig, viteManifest, allDynamicCssFiles, entryFilePath, route) => {
2553
2563
  let entryChunk = resolveChunk(ctx, viteManifest, entryFilePath);
2554
2564
  invariant(entryChunk, `Chunk not found: ${entryFilePath}`);
2555
2565
  let isRootRoute = Boolean(route && route.parentId === void 0);
@@ -2582,7 +2592,10 @@ var getReactRouterManifestBuildAssets = (ctx, viteConfig, viteManifest, entryFil
2582
2592
  // in the manifest that isn't tied to any route file. If we want to render these
2583
2593
  // styles correctly, we need to include them in the root route.
2584
2594
  isRootRoute ? getCssCodeSplitDisabledFile(ctx, viteConfig, viteManifest) : null,
2585
- chunks.flatMap((e) => e.css ?? []).map((href) => `${ctx.publicPath}${href}`)
2595
+ chunks.flatMap((e) => e.css ?? []).map((href) => {
2596
+ let publicHref = `${ctx.publicPath}${href}`;
2597
+ return allDynamicCssFiles.has(href) ? `${publicHref}#` : publicHref;
2598
+ })
2586
2599
  ].flat(1).filter(isNonNullable)
2587
2600
  )
2588
2601
  };
@@ -2605,6 +2618,44 @@ function resolveDependantChunks(viteManifest, entryChunks) {
2605
2618
  }
2606
2619
  return Array.from(chunks);
2607
2620
  }
2621
+ function getAllDynamicCssFiles(ctx, viteManifest) {
2622
+ let allDynamicCssFiles = /* @__PURE__ */ new Set();
2623
+ for (let route of Object.values(ctx.reactRouterConfig.routes)) {
2624
+ let routeFile = path6.join(ctx.reactRouterConfig.appDirectory, route.file);
2625
+ let entryChunk = resolveChunk(
2626
+ ctx,
2627
+ viteManifest,
2628
+ `${routeFile}${BUILD_CLIENT_ROUTE_QUERY_STRING}`
2629
+ );
2630
+ if (entryChunk) {
2631
+ let walk2 = function(chunk, isDynamicImportContext) {
2632
+ if (visitedChunks.has(chunk)) {
2633
+ return;
2634
+ }
2635
+ visitedChunks.add(chunk);
2636
+ if (isDynamicImportContext && chunk.css) {
2637
+ for (let cssFile of chunk.css) {
2638
+ allDynamicCssFiles.add(cssFile);
2639
+ }
2640
+ }
2641
+ if (chunk.dynamicImports) {
2642
+ for (let dynamicImportKey of chunk.dynamicImports) {
2643
+ walk2(viteManifest[dynamicImportKey], true);
2644
+ }
2645
+ }
2646
+ if (chunk.imports) {
2647
+ for (let importKey of chunk.imports) {
2648
+ walk2(viteManifest[importKey], isDynamicImportContext);
2649
+ }
2650
+ }
2651
+ };
2652
+ var walk = walk2;
2653
+ let visitedChunks = /* @__PURE__ */ new Set();
2654
+ walk2(entryChunk, false);
2655
+ }
2656
+ }
2657
+ return allDynamicCssFiles;
2658
+ }
2608
2659
  function dedupe(array2) {
2609
2660
  return [...new Set(array2)];
2610
2661
  }
@@ -2894,10 +2945,12 @@ var reactRouterVitePlugin = () => {
2894
2945
  let viteManifest = await loadViteManifest(
2895
2946
  getClientBuildDirectory(ctx.reactRouterConfig)
2896
2947
  );
2948
+ let allDynamicCssFiles = getAllDynamicCssFiles(ctx, viteManifest);
2897
2949
  let entry = getReactRouterManifestBuildAssets(
2898
2950
  ctx,
2899
2951
  viteConfig2,
2900
2952
  viteManifest,
2953
+ allDynamicCssFiles,
2901
2954
  ctx.entryClientFilePath,
2902
2955
  null
2903
2956
  );
@@ -2949,6 +3002,7 @@ var reactRouterVitePlugin = () => {
2949
3002
  ctx,
2950
3003
  viteConfig2,
2951
3004
  viteManifest,
3005
+ allDynamicCssFiles,
2952
3006
  `${routeFile}${BUILD_CLIENT_ROUTE_QUERY_STRING}`,
2953
3007
  route
2954
3008
  ),
@@ -3778,7 +3832,7 @@ var reactRouterVitePlugin = () => {
3778
3832
  "",
3779
3833
  ` But other route exports in '${importerShort}' depend on '${id}'.`,
3780
3834
  "",
3781
- " See https://remix.run/docs/en/main/guides/vite#splitting-up-client-and-server-code",
3835
+ " See https://reactrouter.com/explanation/code-splitting#removal-of-server-code",
3782
3836
  ""
3783
3837
  ].join("\n")
3784
3838
  );
@@ -3789,7 +3843,7 @@ var reactRouterVitePlugin = () => {
3789
3843
  "",
3790
3844
  ` '${id}' imported by '${importerShort}'`,
3791
3845
  "",
3792
- " See https://remix.run/docs/en/main/guides/vite#splitting-up-client-and-server-code",
3846
+ " See https://reactrouter.com/explanation/code-splitting#removal-of-server-code",
3793
3847
  ""
3794
3848
  ].join("\n")
3795
3849
  );
@@ -4202,10 +4256,10 @@ async function handlePrerender(viteConfig, reactRouterConfig, serverBuildDirecto
4202
4256
  }
4203
4257
  }
4204
4258
  let buildRoutes = createPrerenderRoutes(build.routes);
4205
- for (let path9 of build.prerender) {
4259
+ let prerenderSinglePath = async (path9) => {
4206
4260
  let matches = (0, import_react_router2.matchRoutes)(buildRoutes, `/${path9}/`.replace(/^\/\/+/, "/"));
4207
4261
  if (!matches) {
4208
- continue;
4262
+ return;
4209
4263
  }
4210
4264
  let leafRoute = matches ? matches[matches.length - 1].route : null;
4211
4265
  let manifestRoute = leafRoute ? build.routes[leafRoute.id]?.module : null;
@@ -4262,7 +4316,13 @@ async function handlePrerender(viteConfig, reactRouterConfig, serverBuildDirecto
4262
4316
  } : void 0
4263
4317
  );
4264
4318
  }
4319
+ };
4320
+ let concurrency = 1;
4321
+ let { prerender } = reactRouterConfig;
4322
+ if (typeof prerender === "object" && "unstable_concurrency" in prerender) {
4323
+ concurrency = prerender.unstable_concurrency ?? 1;
4265
4324
  }
4325
+ await (0, import_p_map.default)(build.prerender, prerenderSinglePath, { concurrency });
4266
4326
  }
4267
4327
  function getStaticPrerenderPaths(routes) {
4268
4328
  let paths = ["/"];
@@ -4378,31 +4438,40 @@ ${content.toString("utf8")}`
4378
4438
  );
4379
4439
  }
4380
4440
  async function getPrerenderPaths(prerender, ssr, routes, logWarning = false) {
4381
- let prerenderPaths = [];
4382
- if (prerender != null && prerender !== false) {
4383
- let prerenderRoutes = createPrerenderRoutes(routes);
4384
- if (prerender === true) {
4385
- let { paths, paramRoutes } = getStaticPrerenderPaths(prerenderRoutes);
4386
- if (logWarning && !ssr && paramRoutes.length > 0) {
4387
- console.warn(
4388
- import_picocolors4.default.yellow(
4389
- [
4390
- "\u26A0\uFE0F Paths with dynamic/splat params cannot be prerendered when using `prerender: true`. You may want to use the `prerender()` API to prerender the following paths:",
4391
- ...paramRoutes.map((p) => " - " + p)
4392
- ].join("\n")
4393
- )
4394
- );
4395
- }
4396
- prerenderPaths = paths;
4397
- } else if (typeof prerender === "function") {
4398
- prerenderPaths = await prerender({
4399
- getStaticPaths: () => getStaticPrerenderPaths(prerenderRoutes).paths
4400
- });
4401
- } else {
4402
- prerenderPaths = prerender || ["/"];
4441
+ if (prerender == null || prerender === false) {
4442
+ return [];
4443
+ }
4444
+ let pathsConfig;
4445
+ if (typeof prerender === "object" && "paths" in prerender) {
4446
+ pathsConfig = prerender.paths;
4447
+ } else {
4448
+ pathsConfig = prerender;
4449
+ }
4450
+ if (pathsConfig === false) {
4451
+ return [];
4452
+ }
4453
+ let prerenderRoutes = createPrerenderRoutes(routes);
4454
+ if (pathsConfig === true) {
4455
+ let { paths, paramRoutes } = getStaticPrerenderPaths(prerenderRoutes);
4456
+ if (logWarning && !ssr && paramRoutes.length > 0) {
4457
+ console.warn(
4458
+ import_picocolors4.default.yellow(
4459
+ [
4460
+ "\u26A0\uFE0F Paths with dynamic/splat params cannot be prerendered when using `prerender: true`. You may want to use the `prerender()` API to prerender the following paths:",
4461
+ ...paramRoutes.map((p) => " - " + p)
4462
+ ].join("\n")
4463
+ )
4464
+ );
4403
4465
  }
4466
+ return paths;
4467
+ }
4468
+ if (typeof pathsConfig === "function") {
4469
+ let paths = await pathsConfig({
4470
+ getStaticPaths: () => getStaticPrerenderPaths(prerenderRoutes).paths
4471
+ });
4472
+ return paths;
4404
4473
  }
4405
- return prerenderPaths;
4474
+ return pathsConfig;
4406
4475
  }
4407
4476
  function groupRoutesByParentId2(manifest) {
4408
4477
  let routes = {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@react-router/dev",
3
- "version": "7.9.4",
3
+ "version": "7.9.5-pre.0",
4
4
  "description": "Dev tools and CLI for React Router",
5
5
  "homepage": "https://reactrouter.com",
6
6
  "bugs": {
@@ -78,6 +78,7 @@
78
78
  "isbot": "^5.1.11",
79
79
  "jsesc": "3.0.2",
80
80
  "lodash": "^4.17.21",
81
+ "p-map": "^7.0.3",
81
82
  "pathe": "^1.1.2",
82
83
  "picocolors": "^1.1.1",
83
84
  "prettier": "^3.6.2",
@@ -86,7 +87,7 @@
86
87
  "tinyglobby": "^0.2.14",
87
88
  "valibot": "^1.1.0",
88
89
  "vite-node": "^3.2.2",
89
- "@react-router/node": "7.9.4"
90
+ "@react-router/node": "7.9.5-pre.0"
90
91
  },
91
92
  "devDependencies": {
92
93
  "@types/babel__core": "^7.20.5",
@@ -109,16 +110,16 @@
109
110
  "vite": "^6.1.0",
110
111
  "wireit": "0.14.9",
111
112
  "wrangler": "^4.23.0",
112
- "react-router": "^7.9.4",
113
- "@react-router/serve": "7.9.4"
113
+ "@react-router/serve": "7.9.5-pre.0",
114
+ "react-router": "^7.9.5-pre.0"
114
115
  },
115
116
  "peerDependencies": {
116
117
  "@vitejs/plugin-rsc": "*",
117
118
  "typescript": "^5.1.0",
118
119
  "vite": "^5.1.0 || ^6.0.0 || ^7.0.0",
119
120
  "wrangler": "^3.28.2 || ^4.0.0",
120
- "@react-router/serve": "^7.9.4",
121
- "react-router": "^7.9.4"
121
+ "@react-router/serve": "^7.9.5-pre.0",
122
+ "react-router": "^7.9.5-pre.0"
122
123
  },
123
124
  "peerDependenciesMeta": {
124
125
  "@vitejs/plugin-rsc": {