@react-router/dev 7.9.6-pre.1 → 7.10.0-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,24 +1,53 @@
1
1
  # `@react-router/dev`
2
2
 
3
- ## 7.9.6-pre.1
3
+ ## 7.10.0-pre.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Stabilize `future.v8_splitRouteModules`, replacing `future.unstable_splitRouteModules` ([#14595](https://github.com/remix-run/react-router/pull/14595))
8
+ - ⚠️ This is a breaking change if you have begun using `future.unstable_splitRouteModules`. Please update your `react-router.config.ts`.
9
+
10
+ - Stabilize `future.v8_viteEnvironmentApi`, replacing `future.unstable_viteEnvironmentApi` ([#14595](https://github.com/remix-run/react-router/pull/14595))
11
+ - ⚠️ This is a breaking change if you have begun using `future.unstable_viteEnvironmentApi`. Please update your `react-router.config.ts`.
4
12
 
5
13
  ### Patch Changes
6
14
 
15
+ - Load environment variables before evaluating `routes.ts` ([#14446](https://github.com/remix-run/react-router/pull/14446))
16
+
17
+ For example, you can now compute your routes based on [`VITE_`-prefixed environment variables](https://vite.dev/guide/env-and-mode#env-variables):
18
+
19
+ ```txt
20
+ # .env
21
+ VITE_ENV_ROUTE=my-route
22
+ ```
23
+
24
+ ```ts
25
+ // app/routes.ts
26
+ import { type RouteConfig, route } from "@react-router/dev/routes";
27
+
28
+ const routes: RouteConfig = [];
29
+ if (import.meta.env.VITE_ENV_ROUTE === "my-route") {
30
+ routes.push(route("my-route", "routes/my-route.tsx"));
31
+ }
32
+
33
+ export default routes;
34
+ ```
35
+
7
36
  - Updated dependencies:
8
- - `react-router@7.9.6-pre.1`
9
- - `@react-router/node@7.9.6-pre.1`
10
- - `@react-router/serve@7.9.6-pre.1`
37
+ - `react-router@7.10.0-pre.0`
38
+ - `@react-router/node@7.10.0-pre.0`
39
+ - `@react-router/serve@7.10.0-pre.0`
11
40
 
12
- ## 7.9.6-pre.0
41
+ ## 7.9.6
13
42
 
14
43
  ### Patch Changes
15
44
 
16
45
  - Use a dynamic `import()` to load ESM-only `p-map` dependency to avoid issues on Node 20.18 and below ([#14492](https://github.com/remix-run/react-router/pull/14492))
17
46
  - Short circuit `HEAD` document requests before calling `renderToPipeableStream` in the default `entry.server.tsx` to more closely align with the [spec](https://httpwg.org/specs/rfc9110.html#HEAD) ([#14488](https://github.com/remix-run/react-router/pull/14488))
18
47
  - Updated dependencies:
19
- - `react-router@7.9.6-pre.0`
20
- - `@react-router/node@7.9.6-pre.0`
21
- - `@react-router/serve@7.9.6-pre.0`
48
+ - `react-router@7.9.6`
49
+ - `@react-router/node@7.9.6`
50
+ - `@react-router/serve@7.9.6`
22
51
 
23
52
  ## 7.9.5
24
53
 
package/dist/cli/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * @react-router/dev v7.9.6-pre.1
3
+ * @react-router/dev v7.10.0-pre.0
4
4
  *
5
5
  * Copyright (c) Remix Software Inc.
6
6
  *
@@ -492,12 +492,23 @@ async function resolveConfig({
492
492
  );
493
493
  }
494
494
  }
495
+ let futureConfig = userAndPresetConfigs.future;
496
+ if (futureConfig?.unstable_splitRouteModules !== void 0) {
497
+ return err(
498
+ 'The "future.unstable_splitRouteModules" flag has been stabilized as "future.v8_splitRouteModules"'
499
+ );
500
+ }
501
+ if (futureConfig?.unstable_viteEnvironmentApi !== void 0) {
502
+ return err(
503
+ 'The "future.unstable_viteEnvironmentApi" flag has been stabilized as "future.v8_viteEnvironmentApi"'
504
+ );
505
+ }
495
506
  let future = {
496
- v8_middleware: userAndPresetConfigs.future?.v8_middleware ?? false,
497
507
  unstable_optimizeDeps: userAndPresetConfigs.future?.unstable_optimizeDeps ?? false,
498
- unstable_splitRouteModules: userAndPresetConfigs.future?.unstable_splitRouteModules ?? false,
499
508
  unstable_subResourceIntegrity: userAndPresetConfigs.future?.unstable_subResourceIntegrity ?? false,
500
- unstable_viteEnvironmentApi: userAndPresetConfigs.future?.unstable_viteEnvironmentApi ?? false
509
+ v8_middleware: userAndPresetConfigs.future?.v8_middleware ?? false,
510
+ v8_splitRouteModules: userAndPresetConfigs.future?.v8_splitRouteModules ?? false,
511
+ v8_viteEnvironmentApi: userAndPresetConfigs.future?.v8_viteEnvironmentApi ?? false
501
512
  };
502
513
  let reactRouterConfig = deepFreeze({
503
514
  appDirectory,
@@ -718,17 +729,17 @@ function isEntryFileDependency(moduleGraph, entryFilepath, filepath, visited = /
718
729
  }
719
730
  return false;
720
731
  }
721
- var import_node_fs, import_node_child_process, import_package_json, import_pathe3, import_chokidar, import_picocolors, import_pick2, import_omit, import_cloneDeep, import_isEqual, excludedConfigPresetKeys, mergeReactRouterConfig, deepFreeze, entryExts;
732
+ var import_node_fs, import_node_child_process, import_pathe3, import_chokidar, import_picocolors, import_pkg_types, import_pick2, import_omit, import_cloneDeep, import_isEqual, excludedConfigPresetKeys, mergeReactRouterConfig, deepFreeze, entryExts;
722
733
  var init_config = __esm({
723
734
  "config/config.ts"() {
724
735
  "use strict";
725
736
  import_node_fs = __toESM(require("fs"));
726
737
  import_node_child_process = require("child_process");
727
- import_package_json = __toESM(require("@npmcli/package-json"));
728
738
  init_vite_node();
729
739
  import_pathe3 = __toESM(require("pathe"));
730
740
  import_chokidar = __toESM(require("chokidar"));
731
741
  import_picocolors = __toESM(require("picocolors"));
742
+ import_pkg_types = require("pkg-types");
732
743
  import_pick2 = __toESM(require("lodash/pick"));
733
744
  import_omit = __toESM(require("lodash/omit"));
734
745
  import_cloneDeep = __toESM(require("lodash/cloneDeep"));
@@ -1673,8 +1684,8 @@ async function getEnvironmentOptionsResolvers(ctx, viteCommand) {
1673
1684
  return mergeEnvironmentOptions(getBaseOptions({ viteUserConfig }), {
1674
1685
  resolve: {
1675
1686
  external: (
1676
- // If `unstable_viteEnvironmentApi` is `true`, `resolve.external` is set in the `configEnvironment` hook
1677
- ctx.reactRouterConfig.future.unstable_viteEnvironmentApi ? void 0 : ssrExternals
1687
+ // If `v8_viteEnvironmentApi` is `true`, `resolve.external` is set in the `configEnvironment` hook
1688
+ ctx.reactRouterConfig.future.v8_viteEnvironmentApi ? void 0 : ssrExternals
1678
1689
  ),
1679
1690
  conditions: [...baseConditions, ...maybeDefaultServerConditions],
1680
1691
  externalConditions: [...baseConditions, ...defaultExternalConditions]
@@ -1689,7 +1700,7 @@ async function getEnvironmentOptionsResolvers(ctx, viteCommand) {
1689
1700
  copyPublicDir: false,
1690
1701
  // The client only uses assets in the public directory
1691
1702
  rollupOptions: {
1692
- input: (ctx.reactRouterConfig.future.unstable_viteEnvironmentApi ? viteUserConfig.environments?.ssr?.build?.rollupOptions?.input : viteUserConfig.build?.rollupOptions?.input) ?? virtual.serverBuild.id,
1703
+ input: (ctx.reactRouterConfig.future.v8_viteEnvironmentApi ? viteUserConfig.environments?.ssr?.build?.rollupOptions?.input : viteUserConfig.build?.rollupOptions?.input) ?? virtual.serverBuild.id,
1693
1704
  output: {
1694
1705
  entryFileNames: serverBuildFile,
1695
1706
  format: serverModuleFormat
@@ -1714,14 +1725,14 @@ async function getEnvironmentOptionsResolvers(ctx, viteCommand) {
1714
1725
  let code = (0, import_node_fs3.readFileSync)(routeFilePath, "utf-8");
1715
1726
  return [
1716
1727
  `${routeFilePath}${BUILD_CLIENT_ROUTE_QUERY_STRING}`,
1717
- ...ctx.reactRouterConfig.future.unstable_splitRouteModules && !isRootRoute ? routeChunkExportNames.map(
1728
+ ...ctx.reactRouterConfig.future.v8_splitRouteModules && !isRootRoute ? routeChunkExportNames.map(
1718
1729
  (exportName) => code.includes(exportName) ? getRouteChunkModuleId(routeFilePath, exportName) : null
1719
1730
  ) : []
1720
1731
  ].filter(isNonNullable);
1721
1732
  }
1722
1733
  )
1723
1734
  ],
1724
- output: (ctx.reactRouterConfig.future.unstable_viteEnvironmentApi ? viteUserConfig?.environments?.client?.build?.rollupOptions?.output : viteUserConfig?.build?.rollupOptions?.output) ?? {
1735
+ output: (ctx.reactRouterConfig.future.v8_viteEnvironmentApi ? viteUserConfig?.environments?.client?.build?.rollupOptions?.output : viteUserConfig?.build?.rollupOptions?.output) ?? {
1725
1736
  entryFileNames: ({ moduleIds }) => {
1726
1737
  let routeChunkModuleId = moduleIds.find(isRouteChunkModuleId);
1727
1738
  let routeChunkName = routeChunkModuleId ? getRouteChunkNameFromModuleId(routeChunkModuleId)?.replace(
@@ -1729,7 +1740,7 @@ async function getEnvironmentOptionsResolvers(ctx, viteCommand) {
1729
1740
  ""
1730
1741
  ) : null;
1731
1742
  let routeChunkSuffix = routeChunkName ? `-${(0, import_kebabCase.default)(routeChunkName)}` : "";
1732
- let assetsDir = (ctx.reactRouterConfig.future.unstable_viteEnvironmentApi ? viteUserConfig?.environments?.client?.build?.assetsDir : null) ?? viteUserConfig?.build?.assetsDir ?? "assets";
1743
+ let assetsDir = (ctx.reactRouterConfig.future.v8_viteEnvironmentApi ? viteUserConfig?.environments?.client?.build?.assetsDir : null) ?? viteUserConfig?.build?.assetsDir ?? "assets";
1733
1744
  return path7.posix.join(
1734
1745
  assetsDir,
1735
1746
  `[name]${routeChunkSuffix}-[hash].js`
@@ -1902,12 +1913,12 @@ async function build(root, viteBuildOptions) {
1902
1913
  }
1903
1914
  let config = configResult.value;
1904
1915
  let viteMajor = parseInt(vite2.version.split(".")[0], 10);
1905
- if (config.future.unstable_viteEnvironmentApi && viteMajor === 5) {
1916
+ if (config.future.v8_viteEnvironmentApi && viteMajor === 5) {
1906
1917
  throw new Error(
1907
- "The future.unstable_viteEnvironmentApi option is not supported in Vite 5"
1918
+ "The future.v8_viteEnvironmentApi option is not supported in Vite 5"
1908
1919
  );
1909
1920
  }
1910
- const useViteEnvironmentApi = config.future.unstable_viteEnvironmentApi || await hasReactRouterRscPlugin({ root, viteBuildOptions });
1921
+ const useViteEnvironmentApi = config.future.v8_viteEnvironmentApi || await hasReactRouterRscPlugin({ root, viteBuildOptions });
1911
1922
  return await (useViteEnvironmentApi ? viteAppBuild(root, viteBuildOptions) : viteBuild(root, viteBuildOptions));
1912
1923
  }
1913
1924
  async function viteAppBuild(root, {
@@ -2142,9 +2153,9 @@ var import_picocolors9 = __toESM(require("picocolors"));
2142
2153
  var import_node_fs4 = require("fs");
2143
2154
  var import_promises3 = require("fs/promises");
2144
2155
  var path8 = __toESM(require("path"));
2145
- var import_package_json2 = __toESM(require("@npmcli/package-json"));
2146
2156
  var import_exit_hook = __toESM(require("exit-hook"));
2147
2157
  var import_picocolors8 = __toESM(require("picocolors"));
2158
+ var import_pkg_types2 = require("pkg-types");
2148
2159
  var import_react_router3 = require("react-router");
2149
2160
  init_config();
2150
2161
 
@@ -2308,8 +2319,8 @@ async function generateEntry(entry, rootDirectory, flags = {}) {
2308
2319
  );
2309
2320
  return;
2310
2321
  }
2311
- let pkgJson = await import_package_json2.default.load(rootDirectory);
2312
- let deps = pkgJson.content.dependencies ?? {};
2322
+ let pkgJson = await (0, import_pkg_types2.readPackageJSON)(rootDirectory);
2323
+ let deps = pkgJson.dependencies ?? {};
2313
2324
  if (!deps["@react-router/node"]) {
2314
2325
  console.error(import_picocolors8.default.red(`No default server entry detected.`));
2315
2326
  return;
package/dist/config.d.ts CHANGED
@@ -37,20 +37,20 @@ type ServerBundlesBuildManifest = BaseBuildManifest & {
37
37
  };
38
38
  type ServerModuleFormat = "esm" | "cjs";
39
39
  interface FutureConfig {
40
+ unstable_optimizeDeps: boolean;
41
+ unstable_subResourceIntegrity: boolean;
40
42
  /**
41
43
  * Enable route middleware
42
44
  */
43
45
  v8_middleware: boolean;
44
- unstable_optimizeDeps: boolean;
45
46
  /**
46
47
  * Automatically split route modules into multiple chunks when possible.
47
48
  */
48
- unstable_splitRouteModules: boolean | "enforce";
49
- unstable_subResourceIntegrity: boolean;
49
+ v8_splitRouteModules: boolean | "enforce";
50
50
  /**
51
- * Use Vite Environment API (experimental)
51
+ * Use Vite Environment API
52
52
  */
53
- unstable_viteEnvironmentApi: boolean;
53
+ v8_viteEnvironmentApi: boolean;
54
54
  }
55
55
  type BuildManifest = DefaultBuildManifest | ServerBundlesBuildManifest;
56
56
  type BuildEndHook = (args: {
package/dist/config.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @react-router/dev v7.9.6-pre.1
2
+ * @react-router/dev v7.10.0-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.6-pre.1
2
+ * @react-router/dev v7.10.0-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.6-pre.1
2
+ * @react-router/dev v7.10.0-pre.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -108,7 +108,6 @@ function getVite() {
108
108
  // config/config.ts
109
109
  var import_node_fs = __toESM(require("fs"));
110
110
  var import_node_child_process = require("child_process");
111
- var import_package_json = __toESM(require("@npmcli/package-json"));
112
111
 
113
112
  // vite/ssr-externals.ts
114
113
  var ssrExternals = isReactRouterRepo() ? [
@@ -188,6 +187,7 @@ async function createContext({
188
187
  var import_pathe3 = __toESM(require("pathe"));
189
188
  var import_chokidar = __toESM(require("chokidar"));
190
189
  var import_picocolors = __toESM(require("picocolors"));
190
+ var import_pkg_types = require("pkg-types");
191
191
  var import_pick2 = __toESM(require("lodash/pick"));
192
192
  var import_omit = __toESM(require("lodash/omit"));
193
193
  var import_cloneDeep = __toESM(require("lodash/cloneDeep"));
@@ -522,12 +522,23 @@ async function resolveConfig({
522
522
  );
523
523
  }
524
524
  }
525
+ let futureConfig = userAndPresetConfigs.future;
526
+ if (futureConfig?.unstable_splitRouteModules !== void 0) {
527
+ return err(
528
+ 'The "future.unstable_splitRouteModules" flag has been stabilized as "future.v8_splitRouteModules"'
529
+ );
530
+ }
531
+ if (futureConfig?.unstable_viteEnvironmentApi !== void 0) {
532
+ return err(
533
+ 'The "future.unstable_viteEnvironmentApi" flag has been stabilized as "future.v8_viteEnvironmentApi"'
534
+ );
535
+ }
525
536
  let future = {
526
- v8_middleware: userAndPresetConfigs.future?.v8_middleware ?? false,
527
537
  unstable_optimizeDeps: userAndPresetConfigs.future?.unstable_optimizeDeps ?? false,
528
- unstable_splitRouteModules: userAndPresetConfigs.future?.unstable_splitRouteModules ?? false,
529
538
  unstable_subResourceIntegrity: userAndPresetConfigs.future?.unstable_subResourceIntegrity ?? false,
530
- unstable_viteEnvironmentApi: userAndPresetConfigs.future?.unstable_viteEnvironmentApi ?? false
539
+ v8_middleware: userAndPresetConfigs.future?.v8_middleware ?? false,
540
+ v8_splitRouteModules: userAndPresetConfigs.future?.v8_splitRouteModules ?? false,
541
+ v8_viteEnvironmentApi: userAndPresetConfigs.future?.v8_viteEnvironmentApi ?? false
531
542
  };
532
543
  let reactRouterConfig = deepFreeze({
533
544
  appDirectory,
@@ -786,7 +797,7 @@ var cloudflareDevProxyVitePlugin = (options = {}) => {
786
797
  };
787
798
  },
788
799
  configEnvironment: async (name, options2) => {
789
- if (!future.unstable_viteEnvironmentApi) {
800
+ if (!future.v8_viteEnvironmentApi) {
790
801
  return;
791
802
  }
792
803
  if (name !== "client") {
package/dist/vite.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @react-router/dev v7.9.6-pre.1
2
+ * @react-router/dev v7.10.0-pre.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -68,7 +68,6 @@ var import_picocolors2 = require("picocolors");
68
68
  // config/config.ts
69
69
  var import_node_fs = __toESM(require("fs"));
70
70
  var import_node_child_process = require("child_process");
71
- var import_package_json = __toESM(require("@npmcli/package-json"));
72
71
 
73
72
  // vite/vite.ts
74
73
  var import_pathe2 = __toESM(require("pathe"));
@@ -192,6 +191,7 @@ async function createContext({
192
191
  var import_pathe3 = __toESM(require("pathe"));
193
192
  var import_chokidar = __toESM(require("chokidar"));
194
193
  var import_picocolors = __toESM(require("picocolors"));
194
+ var import_pkg_types = require("pkg-types");
195
195
  var import_pick2 = __toESM(require("lodash/pick"));
196
196
  var import_omit = __toESM(require("lodash/omit"));
197
197
  var import_cloneDeep = __toESM(require("lodash/cloneDeep"));
@@ -549,12 +549,23 @@ async function resolveConfig({
549
549
  );
550
550
  }
551
551
  }
552
+ let futureConfig = userAndPresetConfigs.future;
553
+ if (futureConfig?.unstable_splitRouteModules !== void 0) {
554
+ return err(
555
+ 'The "future.unstable_splitRouteModules" flag has been stabilized as "future.v8_splitRouteModules"'
556
+ );
557
+ }
558
+ if (futureConfig?.unstable_viteEnvironmentApi !== void 0) {
559
+ return err(
560
+ 'The "future.unstable_viteEnvironmentApi" flag has been stabilized as "future.v8_viteEnvironmentApi"'
561
+ );
562
+ }
552
563
  let future = {
553
- v8_middleware: userAndPresetConfigs.future?.v8_middleware ?? false,
554
564
  unstable_optimizeDeps: userAndPresetConfigs.future?.unstable_optimizeDeps ?? false,
555
- unstable_splitRouteModules: userAndPresetConfigs.future?.unstable_splitRouteModules ?? false,
556
565
  unstable_subResourceIntegrity: userAndPresetConfigs.future?.unstable_subResourceIntegrity ?? false,
557
- unstable_viteEnvironmentApi: userAndPresetConfigs.future?.unstable_viteEnvironmentApi ?? false
566
+ v8_middleware: userAndPresetConfigs.future?.v8_middleware ?? false,
567
+ v8_splitRouteModules: userAndPresetConfigs.future?.v8_splitRouteModules ?? false,
568
+ v8_viteEnvironmentApi: userAndPresetConfigs.future?.v8_viteEnvironmentApi ?? false
558
569
  };
559
570
  let reactRouterConfig = deepFreeze({
560
571
  appDirectory,
@@ -736,8 +747,8 @@ async function resolveEntryFiles({
736
747
  );
737
748
  }
738
749
  let packageJsonDirectory = import_pathe3.default.dirname(packageJsonPath);
739
- let pkgJson = await import_package_json.default.load(packageJsonDirectory);
740
- let deps = pkgJson.content.dependencies ?? {};
750
+ let pkgJson = await (0, import_pkg_types.readPackageJSON)(packageJsonDirectory);
751
+ let deps = pkgJson.dependencies ?? {};
741
752
  if (!deps["@react-router/node"]) {
742
753
  throw new Error(
743
754
  `Could not determine server runtime. Please install @react-router/node, or provide a custom entry.server.tsx/jsx file in your app directory.`
@@ -747,13 +758,11 @@ async function resolveEntryFiles({
747
758
  console.log(
748
759
  "adding `isbot@5` to your package.json, you should commit this change"
749
760
  );
750
- pkgJson.update({
751
- dependencies: {
752
- ...pkgJson.content.dependencies,
753
- isbot: "^5"
754
- }
761
+ await (0, import_pkg_types.updatePackage)(packageJsonPath, (pkg) => {
762
+ pkg.dependencies ??= {};
763
+ pkg.dependencies.isbot = "^5";
764
+ (0, import_pkg_types.sortPackage)(pkg);
755
765
  });
756
- await pkgJson.save();
757
766
  let packageManager = detectPackageManager() ?? "npm";
758
767
  (0, import_node_child_process.execSync)(`${packageManager} install`, {
759
768
  cwd: packageJsonDirectory,
@@ -2737,7 +2746,7 @@ var getServerBundleRouteIds = (vitePluginContext, ctx) => {
2737
2746
  if (!ctx.buildManifest) {
2738
2747
  return void 0;
2739
2748
  }
2740
- let environmentName = ctx.reactRouterConfig.future.unstable_viteEnvironmentApi ? vitePluginContext.environment.name : ctx.environmentBuildContext?.name;
2749
+ let environmentName = ctx.reactRouterConfig.future.v8_viteEnvironmentApi ? vitePluginContext.environment.name : ctx.environmentBuildContext?.name;
2741
2750
  if (!environmentName || !isSsrBundleEnvironmentName(environmentName)) {
2742
2751
  return void 0;
2743
2752
  }
@@ -2787,7 +2796,7 @@ var reactRouterVitePlugin = () => {
2787
2796
  }
2788
2797
  return;
2789
2798
  }
2790
- let injectedPluginContext = !reactRouterConfig.future.unstable_viteEnvironmentApi && viteCommand === "build" ? extractPluginContext(viteUserConfig) : void 0;
2799
+ let injectedPluginContext = !reactRouterConfig.future.v8_viteEnvironmentApi && viteCommand === "build" ? extractPluginContext(viteUserConfig) : void 0;
2791
2800
  let { entryClientFilePath, entryServerFilePath } = await resolveEntryFiles({
2792
2801
  rootDirectory,
2793
2802
  reactRouterConfig
@@ -2881,7 +2890,7 @@ var reactRouterVitePlugin = () => {
2881
2890
  }`;
2882
2891
  }).join(",\n ")}
2883
2892
  };
2884
- ${ctx.reactRouterConfig.future.unstable_viteEnvironmentApi && viteCommand === "serve" ? `
2893
+ ${ctx.reactRouterConfig.future.v8_viteEnvironmentApi && viteCommand === "serve" ? `
2885
2894
  export const unstable_getCriticalCss = ({ pathname }) => {
2886
2895
  return {
2887
2896
  rel: "stylesheet",
@@ -2959,7 +2968,7 @@ var reactRouterVitePlugin = () => {
2959
2968
  viteChildCompiler,
2960
2969
  ctx
2961
2970
  );
2962
- let enforceSplitRouteModules = ctx.reactRouterConfig.future.unstable_splitRouteModules === "enforce";
2971
+ let enforceSplitRouteModules = ctx.reactRouterConfig.future.v8_splitRouteModules === "enforce";
2963
2972
  for (let route of Object.values(ctx.reactRouterConfig.routes)) {
2964
2973
  let routeFile = path6.join(ctx.reactRouterConfig.appDirectory, route.file);
2965
2974
  let sourceExports = routeManifestExports[route.id];
@@ -3071,7 +3080,7 @@ var reactRouterVitePlugin = () => {
3071
3080
  viteChildCompiler,
3072
3081
  ctx
3073
3082
  );
3074
- let enforceSplitRouteModules = ctx.reactRouterConfig.future.unstable_splitRouteModules === "enforce";
3083
+ let enforceSplitRouteModules = ctx.reactRouterConfig.future.v8_splitRouteModules === "enforce";
3075
3084
  for (let [key, route] of Object.entries(ctx.reactRouterConfig.routes)) {
3076
3085
  let routeFile = route.file;
3077
3086
  let sourceExports = routeManifestExports[key];
@@ -3190,17 +3199,17 @@ var reactRouterVitePlugin = () => {
3190
3199
  logger: vite2.createLogger("warn", { prefix: "[react-router]" })
3191
3200
  });
3192
3201
  }
3202
+ await loadDotenv({
3203
+ rootDirectory,
3204
+ viteUserConfig,
3205
+ mode
3206
+ });
3193
3207
  reactRouterConfigLoader = await createConfigLoader({
3194
3208
  rootDirectory,
3195
3209
  mode,
3196
3210
  watch: viteCommand === "serve"
3197
3211
  });
3198
3212
  await updatePluginContext();
3199
- await loadDotenv({
3200
- rootDirectory,
3201
- viteUserConfig,
3202
- mode
3203
- });
3204
3213
  let environments = await getEnvironmentsOptions(ctx, viteCommand, {
3205
3214
  viteUserConfig
3206
3215
  });
@@ -3266,7 +3275,7 @@ var reactRouterVitePlugin = () => {
3266
3275
  // will throw an error that the file is not allowed to be read.
3267
3276
  // https://vitejs.dev/config/server-options#server-fs-allow
3268
3277
  server: viteUserConfig.server?.fs?.allow ? { fs: { allow: defaultEntries } } : void 0,
3269
- ...ctx.reactRouterConfig.future.unstable_viteEnvironmentApi ? {
3278
+ ...ctx.reactRouterConfig.future.v8_viteEnvironmentApi ? {
3270
3279
  environments,
3271
3280
  build: {
3272
3281
  // This isn't honored by the SSR environment config (which seems
@@ -3305,7 +3314,7 @@ var reactRouterVitePlugin = () => {
3305
3314
  };
3306
3315
  },
3307
3316
  configEnvironment(name, options) {
3308
- if (ctx.reactRouterConfig.future.unstable_viteEnvironmentApi && (ctx.buildManifest?.serverBundles ? isSsrBundleEnvironmentName(name) : name === "ssr")) {
3317
+ if (ctx.reactRouterConfig.future.v8_viteEnvironmentApi && (ctx.buildManifest?.serverBundles ? isSsrBundleEnvironmentName(name) : name === "ssr")) {
3309
3318
  const vite2 = getVite();
3310
3319
  return {
3311
3320
  resolve: {
@@ -3441,7 +3450,7 @@ var reactRouterVitePlugin = () => {
3441
3450
  }
3442
3451
  }
3443
3452
  );
3444
- if (ctx.reactRouterConfig.future.unstable_viteEnvironmentApi) {
3453
+ if (ctx.reactRouterConfig.future.v8_viteEnvironmentApi) {
3445
3454
  viteDevServer.middlewares.use(async (req, res, next) => {
3446
3455
  let [reqPathname, reqSearch] = (req.url ?? "").split("?");
3447
3456
  if (reqPathname.endsWith("/@react-router/critical.css")) {
@@ -3469,7 +3478,7 @@ var reactRouterVitePlugin = () => {
3469
3478
  viteDevServer.middlewares.use(async (req, res, next) => {
3470
3479
  try {
3471
3480
  let build;
3472
- if (ctx.reactRouterConfig.future.unstable_viteEnvironmentApi) {
3481
+ if (ctx.reactRouterConfig.future.v8_viteEnvironmentApi) {
3473
3482
  let vite2 = getVite();
3474
3483
  let ssrEnvironment = viteDevServer.environments.ssr;
3475
3484
  if (!vite2.isRunnableDevEnvironment(ssrEnvironment)) {
@@ -3506,17 +3515,17 @@ var reactRouterVitePlugin = () => {
3506
3515
  // the SSR build and move server-only assets to client assets directory
3507
3516
  async handler() {
3508
3517
  let { future } = ctx.reactRouterConfig;
3509
- if (future.unstable_viteEnvironmentApi ? this.environment.name === "client" : !viteConfigEnv.isSsrBuild) {
3518
+ if (future.v8_viteEnvironmentApi ? this.environment.name === "client" : !viteConfigEnv.isSsrBuild) {
3510
3519
  return;
3511
3520
  }
3512
3521
  invariant(viteConfig);
3513
3522
  let clientBuildDirectory = getClientBuildDirectory(
3514
3523
  ctx.reactRouterConfig
3515
3524
  );
3516
- let serverBuildDirectory = future.unstable_viteEnvironmentApi ? this.environment.config?.build?.outDir : ctx.environmentBuildContext?.options.build?.outDir ?? getServerBuildDirectory(ctx.reactRouterConfig);
3525
+ let serverBuildDirectory = future.v8_viteEnvironmentApi ? this.environment.config?.build?.outDir : ctx.environmentBuildContext?.options.build?.outDir ?? getServerBuildDirectory(ctx.reactRouterConfig);
3517
3526
  let ssrViteManifest = await loadViteManifest(serverBuildDirectory);
3518
3527
  let ssrAssetPaths = getViteManifestAssetPaths(ssrViteManifest);
3519
- let userSsrEmitAssets = (ctx.reactRouterConfig.future.unstable_viteEnvironmentApi ? viteUserConfig.environments?.ssr?.build?.ssrEmitAssets ?? viteUserConfig.environments?.ssr?.build?.emitAssets : null) ?? viteUserConfig.build?.ssrEmitAssets ?? false;
3528
+ let userSsrEmitAssets = (ctx.reactRouterConfig.future.v8_viteEnvironmentApi ? viteUserConfig.environments?.ssr?.build?.ssrEmitAssets ?? viteUserConfig.environments?.ssr?.build?.emitAssets : null) ?? viteUserConfig.build?.ssrEmitAssets ?? false;
3520
3529
  let movedAssetPaths = [];
3521
3530
  let removedAssetPaths = [];
3522
3531
  let copiedAssetPaths = [];
@@ -3730,7 +3739,7 @@ var reactRouterVitePlugin = () => {
3730
3739
  reason: "Split round modules disabled"
3731
3740
  });
3732
3741
  }
3733
- let enforceSplitRouteModules = ctx.reactRouterConfig.future.unstable_splitRouteModules === "enforce";
3742
+ let enforceSplitRouteModules = ctx.reactRouterConfig.future.v8_splitRouteModules === "enforce";
3734
3743
  if (enforceSplitRouteModules && chunkName === "main" && chunk) {
3735
3744
  let exportNames = getExportNames(chunk.code);
3736
3745
  validateRouteChunks({
@@ -4642,7 +4651,7 @@ async function detectRouteChunksIfEnabled(cache, ctx, id, input) {
4642
4651
  }
4643
4652
  };
4644
4653
  }
4645
- if (!ctx.reactRouterConfig.future.unstable_splitRouteModules) {
4654
+ if (!ctx.reactRouterConfig.future.v8_splitRouteModules) {
4646
4655
  return noRouteChunks();
4647
4656
  }
4648
4657
  if (isRootRouteModuleId(ctx, id)) {
@@ -4656,7 +4665,7 @@ async function detectRouteChunksIfEnabled(cache, ctx, id, input) {
4656
4665
  return detectRouteChunks(code, cache, cacheKey);
4657
4666
  }
4658
4667
  async function getRouteChunkIfEnabled(cache, ctx, id, chunkName, input) {
4659
- if (!ctx.reactRouterConfig.future.unstable_splitRouteModules) {
4668
+ if (!ctx.reactRouterConfig.future.v8_splitRouteModules) {
4660
4669
  return null;
4661
4670
  }
4662
4671
  let code = await resolveRouteFileCode(ctx, input);
@@ -4760,7 +4769,7 @@ async function getBuildManifest({
4760
4769
  if (typeof serverBundleId !== "string") {
4761
4770
  throw new Error(`The "serverBundles" function must return a string`);
4762
4771
  }
4763
- if (reactRouterConfig.future.unstable_viteEnvironmentApi) {
4772
+ if (reactRouterConfig.future.v8_viteEnvironmentApi) {
4764
4773
  if (!/^[a-zA-Z0-9_]+$/.test(serverBundleId)) {
4765
4774
  throw new Error(
4766
4775
  `The "serverBundles" function must only return strings containing alphanumeric characters and underscores.`
@@ -4848,8 +4857,8 @@ async function getEnvironmentOptionsResolvers(ctx, viteCommand) {
4848
4857
  return mergeEnvironmentOptions(getBaseOptions({ viteUserConfig }), {
4849
4858
  resolve: {
4850
4859
  external: (
4851
- // If `unstable_viteEnvironmentApi` is `true`, `resolve.external` is set in the `configEnvironment` hook
4852
- ctx.reactRouterConfig.future.unstable_viteEnvironmentApi ? void 0 : ssrExternals
4860
+ // If `v8_viteEnvironmentApi` is `true`, `resolve.external` is set in the `configEnvironment` hook
4861
+ ctx.reactRouterConfig.future.v8_viteEnvironmentApi ? void 0 : ssrExternals
4853
4862
  ),
4854
4863
  conditions: [...baseConditions, ...maybeDefaultServerConditions],
4855
4864
  externalConditions: [...baseConditions, ...defaultExternalConditions]
@@ -4864,7 +4873,7 @@ async function getEnvironmentOptionsResolvers(ctx, viteCommand) {
4864
4873
  copyPublicDir: false,
4865
4874
  // The client only uses assets in the public directory
4866
4875
  rollupOptions: {
4867
- input: (ctx.reactRouterConfig.future.unstable_viteEnvironmentApi ? viteUserConfig.environments?.ssr?.build?.rollupOptions?.input : viteUserConfig.build?.rollupOptions?.input) ?? virtual.serverBuild.id,
4876
+ input: (ctx.reactRouterConfig.future.v8_viteEnvironmentApi ? viteUserConfig.environments?.ssr?.build?.rollupOptions?.input : viteUserConfig.build?.rollupOptions?.input) ?? virtual.serverBuild.id,
4868
4877
  output: {
4869
4878
  entryFileNames: serverBuildFile,
4870
4879
  format: serverModuleFormat
@@ -4889,14 +4898,14 @@ async function getEnvironmentOptionsResolvers(ctx, viteCommand) {
4889
4898
  let code = (0, import_node_fs2.readFileSync)(routeFilePath, "utf-8");
4890
4899
  return [
4891
4900
  `${routeFilePath}${BUILD_CLIENT_ROUTE_QUERY_STRING}`,
4892
- ...ctx.reactRouterConfig.future.unstable_splitRouteModules && !isRootRoute ? routeChunkExportNames.map(
4901
+ ...ctx.reactRouterConfig.future.v8_splitRouteModules && !isRootRoute ? routeChunkExportNames.map(
4893
4902
  (exportName) => code.includes(exportName) ? getRouteChunkModuleId(routeFilePath, exportName) : null
4894
4903
  ) : []
4895
4904
  ].filter(isNonNullable);
4896
4905
  }
4897
4906
  )
4898
4907
  ],
4899
- output: (ctx.reactRouterConfig.future.unstable_viteEnvironmentApi ? viteUserConfig?.environments?.client?.build?.rollupOptions?.output : viteUserConfig?.build?.rollupOptions?.output) ?? {
4908
+ output: (ctx.reactRouterConfig.future.v8_viteEnvironmentApi ? viteUserConfig?.environments?.client?.build?.rollupOptions?.output : viteUserConfig?.build?.rollupOptions?.output) ?? {
4900
4909
  entryFileNames: ({ moduleIds }) => {
4901
4910
  let routeChunkModuleId = moduleIds.find(isRouteChunkModuleId);
4902
4911
  let routeChunkName = routeChunkModuleId ? getRouteChunkNameFromModuleId(routeChunkModuleId)?.replace(
@@ -4904,7 +4913,7 @@ async function getEnvironmentOptionsResolvers(ctx, viteCommand) {
4904
4913
  ""
4905
4914
  ) : null;
4906
4915
  let routeChunkSuffix = routeChunkName ? `-${(0, import_kebabCase.default)(routeChunkName)}` : "";
4907
- let assetsDir = (ctx.reactRouterConfig.future.unstable_viteEnvironmentApi ? viteUserConfig?.environments?.client?.build?.assetsDir : null) ?? viteUserConfig?.build?.assetsDir ?? "assets";
4916
+ let assetsDir = (ctx.reactRouterConfig.future.v8_viteEnvironmentApi ? viteUserConfig?.environments?.client?.build?.assetsDir : null) ?? viteUserConfig?.build?.assetsDir ?? "assets";
4908
4917
  return path6.posix.join(
4909
4918
  assetsDir,
4910
4919
  `[name]${routeChunkSuffix}-[hash].js`
@@ -5337,6 +5346,11 @@ function reactRouterRSCVitePlugin() {
5337
5346
  viteCommand = command;
5338
5347
  const rootDirectory = getRootDirectory(viteUserConfig);
5339
5348
  const watch2 = command === "serve";
5349
+ await loadDotenv({
5350
+ rootDirectory,
5351
+ viteUserConfig,
5352
+ mode
5353
+ });
5340
5354
  configLoader = await createConfigLoader({
5341
5355
  rootDirectory,
5342
5356
  mode,
@@ -5349,12 +5363,12 @@ function reactRouterRSCVitePlugin() {
5349
5363
  if (userConfig.routeDiscovery) errors.push("routeDiscovery");
5350
5364
  if (userConfig.serverBundles) errors.push("serverBundles");
5351
5365
  if (userConfig.ssr === false) errors.push("ssr: false");
5352
- if (userConfig.future?.unstable_splitRouteModules)
5353
- errors.push("future.unstable_splitRouteModules");
5354
- if (userConfig.future?.unstable_viteEnvironmentApi === false)
5355
- errors.push("future.unstable_viteEnvironmentApi: false");
5356
5366
  if (userConfig.future?.v8_middleware === false)
5357
5367
  errors.push("future.v8_middleware: false");
5368
+ if (userConfig.future?.v8_splitRouteModules)
5369
+ errors.push("future.v8_splitRouteModules");
5370
+ if (userConfig.future?.v8_viteEnvironmentApi === false)
5371
+ errors.push("future.v8_viteEnvironmentApi: false");
5358
5372
  if (userConfig.future?.unstable_subResourceIntegrity)
5359
5373
  errors.push("future.unstable_subResourceIntegrity");
5360
5374
  if (errors.length) {
@@ -5372,11 +5386,6 @@ ${errors.map((x) => ` - ${x}`).join("\n")}
5372
5386
  "When using the React Router `basename` and the Vite `base` config, the `basename` config must begin with `base` for the default Vite dev server."
5373
5387
  );
5374
5388
  }
5375
- await loadDotenv({
5376
- rootDirectory,
5377
- viteUserConfig,
5378
- mode
5379
- });
5380
5389
  const vite2 = await import("vite");
5381
5390
  logger = vite2.createLogger(viteUserConfig.logLevel, {
5382
5391
  prefix: "[react-router]"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@react-router/dev",
3
- "version": "7.9.6-pre.1",
3
+ "version": "7.10.0-pre.0",
4
4
  "description": "Dev tools and CLI for React Router",
5
5
  "homepage": "https://reactrouter.com",
6
6
  "bugs": {
@@ -67,7 +67,6 @@
67
67
  "@babel/preset-typescript": "^7.27.1",
68
68
  "@babel/traverse": "^7.27.7",
69
69
  "@babel/types": "^7.27.7",
70
- "@npmcli/package-json": "^4.0.1",
71
70
  "@remix-run/node-fetch-server": "^0.9.0",
72
71
  "arg": "^5.0.1",
73
72
  "babel-dead-code-elimination": "^1.0.6",
@@ -81,13 +80,14 @@
81
80
  "p-map": "^7.0.3",
82
81
  "pathe": "^1.1.2",
83
82
  "picocolors": "^1.1.1",
83
+ "pkg-types": "^2.3.0",
84
84
  "prettier": "^3.6.2",
85
85
  "react-refresh": "^0.14.0",
86
86
  "semver": "^7.3.7",
87
87
  "tinyglobby": "^0.2.14",
88
88
  "valibot": "^1.1.0",
89
89
  "vite-node": "^3.2.2",
90
- "@react-router/node": "7.9.6-pre.1"
90
+ "@react-router/node": "7.10.0-pre.0"
91
91
  },
92
92
  "devDependencies": {
93
93
  "@types/babel__core": "^7.20.5",
@@ -107,19 +107,19 @@
107
107
  "fast-glob": "3.2.11",
108
108
  "tsup": "^8.3.0",
109
109
  "typescript": "^5.1.6",
110
- "vite": "^6.1.0",
110
+ "vite": "^6.3.0",
111
111
  "wireit": "0.14.9",
112
112
  "wrangler": "^4.23.0",
113
- "@react-router/serve": "7.9.6-pre.1",
114
- "react-router": "^7.9.6-pre.1"
113
+ "@react-router/serve": "7.10.0-pre.0",
114
+ "react-router": "^7.10.0-pre.0"
115
115
  },
116
116
  "peerDependencies": {
117
117
  "@vitejs/plugin-rsc": "*",
118
118
  "typescript": "^5.1.0",
119
119
  "vite": "^5.1.0 || ^6.0.0 || ^7.0.0",
120
120
  "wrangler": "^3.28.2 || ^4.0.0",
121
- "@react-router/serve": "^7.9.6-pre.1",
122
- "react-router": "^7.9.6-pre.1"
121
+ "@react-router/serve": "^7.10.0-pre.0",
122
+ "react-router": "^7.10.0-pre.0"
123
123
  },
124
124
  "peerDependenciesMeta": {
125
125
  "@vitejs/plugin-rsc": {