@react-router/dev 7.16.0 → 7.18.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,15 +1,46 @@
1
1
  # `@react-router/dev`
2
2
 
3
+ ## v7.18.0
4
+
5
+ ### Patch Changes
6
+
7
+ - Pass Vite `server.watch` config to child compiler in development mode. ([#15178](https://github.com/remix-run/react-router/pull/15178))
8
+
9
+ - Ignore external Vite server environments in Framework Mode build hooks ([#14883](https://github.com/remix-run/react-router/pull/14883))
10
+
11
+ When `future.v8_viteEnvironmentApi` is enabled, React Router previously treated any non-client Vite environment as its own server build. This caused issues with integrations like Nitro, where plugins can register additional environments.
12
+
13
+ Framework Mode build hooks now ignore external server environments and only process the app's own server build.
14
+
15
+ - Updated dependencies:
16
+ - [`react-router@7.18.0`](https://github.com/remix-run/react-router/releases/tag/react-router@7.18.0)
17
+ - [`@react-router/node@7.18.0`](https://github.com/remix-run/react-router/releases/tag/@react-router/node@7.18.0)
18
+ - [`@react-router/serve@7.18.0`](https://github.com/remix-run/react-router/releases/tag/@react-router/serve@7.18.0)
19
+
20
+ ## v7.17.0
21
+
22
+ ### Patch Changes
23
+
24
+ - Fix future flag warning URLs and only log each future flag warning one time ([#15138](https://github.com/remix-run/react-router/pull/15138))
25
+
26
+ ### Unstable Changes
27
+
28
+ ⚠️ _[Unstable features](https://reactrouter.com/community/api-development-strategy#unstable-flags) are not recommended for production use_
29
+
30
+ - Prevent RSC route module server exports from being scanned by the client dependency optimizer when `future.unstable_optimizeDeps` is enabled. ([#15005](https://github.com/remix-run/react-router/pull/15005))
31
+ - Updated dependencies:
32
+ - [`react-router@7.17.0`](https://github.com/remix-run/react-router/releases/tag/react-router@7.17.0)
33
+ - [`@react-router/node@7.17.0`](https://github.com/remix-run/react-router/releases/tag/@react-router/node@7.17.0)
34
+ - [`@react-router/serve@7.17.0`](https://github.com/remix-run/react-router/releases/tag/@react-router/serve@7.17.0)
35
+
3
36
  ## v7.16.0
4
37
 
5
38
  ### Minor Changes
6
39
 
7
40
  - Stabilize `future.unstable_trailingSlashAwareDataRequests` as `future.v8_trailingSlashAwareDataRequests` ([#15098](https://github.com/remix-run/react-router/pull/15098))
8
-
9
41
  - The unstable flag is no longer supported and will error during config resolution
10
42
 
11
43
  - Log future flag warnings for upcoming React Router v8 flags ([#15029](https://github.com/remix-run/react-router/pull/15029))
12
-
13
44
  - `v8_middleware`, `v8_splitRouteModules`, `v8_viteEnvironmentApi`, `v8_passThroughRequests`, `v8_trailingSlashAwareDataRequests`
14
45
 
15
46
  ### Patch Changes
package/dist/cli/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * @react-router/dev v7.16.0
3
+ * @react-router/dev v7.18.0
4
4
  *
5
5
  * Copyright (c) Remix Software Inc.
6
6
  *
@@ -312,7 +312,8 @@ async function resolveConfig({
312
312
  viteNodeContext,
313
313
  reactRouterConfigFile,
314
314
  skipRoutes,
315
- validateConfig
315
+ validateConfig,
316
+ shouldLogFutureFlagWarnings
316
317
  }) {
317
318
  let reactRouterUserConfig = {};
318
319
  if (reactRouterConfigFile) {
@@ -556,7 +557,9 @@ async function resolveConfig({
556
557
  for (let preset of reactRouterUserConfig.presets ?? []) {
557
558
  await preset.reactRouterConfigResolved?.({ reactRouterConfig });
558
559
  }
559
- logFutureFlagWarnings(userAndPresetConfigs.future || {});
560
+ if (shouldLogFutureFlagWarnings) {
561
+ logFutureFlagWarnings(userAndPresetConfigs.future || {});
562
+ }
560
563
  return ok(reactRouterConfig);
561
564
  }
562
565
  function logFutureFlagWarning(flag, message) {
@@ -564,7 +567,7 @@ function logFutureFlagWarning(flag, message) {
564
567
  import_picocolors.default.yellow(
565
568
  ` \u26A0\uFE0F Future Flag Warning: ${message}
566
569
  You can use the \`future.${flag}\` flag to opt in early.
567
- -> https://reactrouter.com/upgrading/future-flags#${flag}`
570
+ -> https://reactrouter.com/v7/upgrading/future#future${flag.toLowerCase()}`
568
571
  )
569
572
  );
570
573
  }
@@ -605,7 +608,8 @@ async function createConfigLoader({
605
608
  watch: watch2,
606
609
  mode,
607
610
  skipRoutes,
608
- validateConfig
611
+ validateConfig,
612
+ shouldLogFutureFlagWarnings
609
613
  }) {
610
614
  root = import_pathe3.default.normalize(root ?? process.env.REACT_ROUTER_ROOT ?? process.cwd());
611
615
  let vite2 = await import("vite");
@@ -629,10 +633,17 @@ async function createConfigLoader({
629
633
  viteNodeContext,
630
634
  reactRouterConfigFile,
631
635
  skipRoutes,
632
- validateConfig
636
+ validateConfig,
637
+ shouldLogFutureFlagWarnings
633
638
  });
634
639
  let appDirectory;
635
- let initialConfigResult = await getConfig();
640
+ let initialConfigResult = await resolveConfig({
641
+ root,
642
+ viteNodeContext,
643
+ reactRouterConfigFile,
644
+ skipRoutes,
645
+ validateConfig
646
+ });
636
647
  if (!initialConfigResult.ok) {
637
648
  throw new Error(initialConfigResult.error);
638
649
  }
@@ -1688,9 +1699,12 @@ function extractPluginContext(viteConfig) {
1688
1699
  function isSsrBundleEnvironmentName(name) {
1689
1700
  return name.startsWith(SSR_BUNDLE_PREFIX);
1690
1701
  }
1702
+ function isReactRouterServerEnvironment(ctx, environmentName) {
1703
+ return ctx.buildManifest?.serverBundles ? isSsrBundleEnvironmentName(environmentName) : environmentName === "ssr";
1704
+ }
1691
1705
  function getServerEnvironmentEntries(ctx, record) {
1692
1706
  return Object.entries(record).filter(
1693
- ([name]) => ctx.buildManifest?.serverBundles ? isSsrBundleEnvironmentName(name) : name === "ssr"
1707
+ ([name]) => isReactRouterServerEnvironment(ctx, name)
1694
1708
  );
1695
1709
  }
1696
1710
  function getServerEnvironmentKeys(ctx, record) {
package/dist/config.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @react-router/dev v7.16.0
2
+ * @react-router/dev v7.18.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.16.0
2
+ * @react-router/dev v7.18.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @react-router/dev v7.16.0
2
+ * @react-router/dev v7.18.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -338,7 +338,8 @@ async function resolveConfig({
338
338
  viteNodeContext,
339
339
  reactRouterConfigFile,
340
340
  skipRoutes,
341
- validateConfig
341
+ validateConfig,
342
+ shouldLogFutureFlagWarnings
342
343
  }) {
343
344
  let reactRouterUserConfig = {};
344
345
  if (reactRouterConfigFile) {
@@ -582,7 +583,9 @@ async function resolveConfig({
582
583
  for (let preset of reactRouterUserConfig.presets ?? []) {
583
584
  await preset.reactRouterConfigResolved?.({ reactRouterConfig });
584
585
  }
585
- logFutureFlagWarnings(userAndPresetConfigs.future || {});
586
+ if (shouldLogFutureFlagWarnings) {
587
+ logFutureFlagWarnings(userAndPresetConfigs.future || {});
588
+ }
586
589
  return ok(reactRouterConfig);
587
590
  }
588
591
  function logFutureFlagWarning(flag, message) {
@@ -590,7 +593,7 @@ function logFutureFlagWarning(flag, message) {
590
593
  import_picocolors.default.yellow(
591
594
  ` \u26A0\uFE0F Future Flag Warning: ${message}
592
595
  You can use the \`future.${flag}\` flag to opt in early.
593
- -> https://reactrouter.com/upgrading/future-flags#${flag}`
596
+ -> https://reactrouter.com/v7/upgrading/future#future${flag.toLowerCase()}`
594
597
  )
595
598
  );
596
599
  }
@@ -631,7 +634,8 @@ async function createConfigLoader({
631
634
  watch,
632
635
  mode,
633
636
  skipRoutes,
634
- validateConfig
637
+ validateConfig,
638
+ shouldLogFutureFlagWarnings
635
639
  }) {
636
640
  root = import_pathe3.default.normalize(root ?? process.env.REACT_ROUTER_ROOT ?? process.cwd());
637
641
  let vite2 = await import("vite");
@@ -655,10 +659,17 @@ async function createConfigLoader({
655
659
  viteNodeContext,
656
660
  reactRouterConfigFile,
657
661
  skipRoutes,
658
- validateConfig
662
+ validateConfig,
663
+ shouldLogFutureFlagWarnings
659
664
  });
660
665
  let appDirectory;
661
- let initialConfigResult = await getConfig();
666
+ let initialConfigResult = await resolveConfig({
667
+ root,
668
+ viteNodeContext,
669
+ reactRouterConfigFile,
670
+ skipRoutes,
671
+ validateConfig
672
+ });
662
673
  if (!initialConfigResult.ok) {
663
674
  throw new Error(initialConfigResult.error);
664
675
  }
package/dist/vite.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @react-router/dev v7.16.0
2
+ * @react-router/dev v7.18.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -375,7 +375,8 @@ async function resolveConfig({
375
375
  viteNodeContext,
376
376
  reactRouterConfigFile,
377
377
  skipRoutes,
378
- validateConfig
378
+ validateConfig,
379
+ shouldLogFutureFlagWarnings
379
380
  }) {
380
381
  let reactRouterUserConfig = {};
381
382
  if (reactRouterConfigFile) {
@@ -619,7 +620,9 @@ async function resolveConfig({
619
620
  for (let preset of reactRouterUserConfig.presets ?? []) {
620
621
  await preset.reactRouterConfigResolved?.({ reactRouterConfig });
621
622
  }
622
- logFutureFlagWarnings(userAndPresetConfigs.future || {});
623
+ if (shouldLogFutureFlagWarnings) {
624
+ logFutureFlagWarnings(userAndPresetConfigs.future || {});
625
+ }
623
626
  return ok(reactRouterConfig);
624
627
  }
625
628
  function logFutureFlagWarning(flag, message) {
@@ -627,7 +630,7 @@ function logFutureFlagWarning(flag, message) {
627
630
  import_picocolors.default.yellow(
628
631
  ` \u26A0\uFE0F Future Flag Warning: ${message}
629
632
  You can use the \`future.${flag}\` flag to opt in early.
630
- -> https://reactrouter.com/upgrading/future-flags#${flag}`
633
+ -> https://reactrouter.com/v7/upgrading/future#future${flag.toLowerCase()}`
631
634
  )
632
635
  );
633
636
  }
@@ -668,7 +671,8 @@ async function createConfigLoader({
668
671
  watch: watch2,
669
672
  mode,
670
673
  skipRoutes,
671
- validateConfig
674
+ validateConfig,
675
+ shouldLogFutureFlagWarnings
672
676
  }) {
673
677
  root = import_pathe3.default.normalize(root ?? process.env.REACT_ROUTER_ROOT ?? process.cwd());
674
678
  let vite2 = await import("vite");
@@ -692,10 +696,17 @@ async function createConfigLoader({
692
696
  viteNodeContext,
693
697
  reactRouterConfigFile,
694
698
  skipRoutes,
695
- validateConfig
699
+ validateConfig,
700
+ shouldLogFutureFlagWarnings
696
701
  });
697
702
  let appDirectory;
698
- let initialConfigResult = await getConfig();
703
+ let initialConfigResult = await resolveConfig({
704
+ root,
705
+ viteNodeContext,
706
+ reactRouterConfigFile,
707
+ skipRoutes,
708
+ validateConfig
709
+ });
699
710
  if (!initialConfigResult.ok) {
700
711
  throw new Error(initialConfigResult.error);
701
712
  }
@@ -2831,9 +2842,12 @@ var SSR_BUNDLE_PREFIX = "ssrBundle_";
2831
2842
  function isSsrBundleEnvironmentName(name) {
2832
2843
  return name.startsWith(SSR_BUNDLE_PREFIX);
2833
2844
  }
2845
+ function isReactRouterServerEnvironment(ctx, environmentName) {
2846
+ return ctx.buildManifest?.serverBundles ? isSsrBundleEnvironmentName(environmentName) : environmentName === "ssr";
2847
+ }
2834
2848
  function getServerEnvironmentEntries(ctx, record) {
2835
2849
  return Object.entries(record).filter(
2836
- ([name]) => ctx.buildManifest?.serverBundles ? isSsrBundleEnvironmentName(name) : name === "ssr"
2850
+ ([name]) => isReactRouterServerEnvironment(ctx, name)
2837
2851
  );
2838
2852
  }
2839
2853
  function getServerEnvironmentValues(ctx, record) {
@@ -3574,7 +3588,8 @@ var reactRouterVitePlugin = () => {
3574
3588
  reactRouterConfigLoader = await createConfigLoader({
3575
3589
  rootDirectory,
3576
3590
  mode,
3577
- watch: viteCommand === "serve"
3591
+ watch: viteCommand === "serve",
3592
+ shouldLogFutureFlagWarnings: viteCommand !== "build" || viteConfigEnv.isSsrBuild === true
3578
3593
  });
3579
3594
  await updatePluginContext();
3580
3595
  let environments = await getEnvironmentsOptions(ctx, viteCommand, {
@@ -3689,7 +3704,7 @@ var reactRouterVitePlugin = () => {
3689
3704
  };
3690
3705
  },
3691
3706
  configEnvironment(name, options) {
3692
- if (ctx.reactRouterConfig.future.v8_viteEnvironmentApi && (ctx.buildManifest?.serverBundles ? isSsrBundleEnvironmentName(name) : name === "ssr")) {
3707
+ if (ctx.reactRouterConfig.future.v8_viteEnvironmentApi && isReactRouterServerEnvironment(ctx, name)) {
3693
3708
  const vite2 = getVite();
3694
3709
  return {
3695
3710
  resolve: {
@@ -3753,7 +3768,7 @@ var reactRouterVitePlugin = () => {
3753
3768
  cacheDir: "node_modules/.vite-child-compiler",
3754
3769
  mode: viteConfig.mode,
3755
3770
  server: {
3756
- watch: viteConfig.command === "build" ? null : void 0,
3771
+ watch: viteConfig.command === "build" ? null : viteConfig.server.watch,
3757
3772
  preTransformRequests: false,
3758
3773
  hmr: false
3759
3774
  },
@@ -3975,7 +3990,7 @@ var reactRouterVitePlugin = () => {
3975
3990
  // the SSR build and move server-only assets to client assets directory
3976
3991
  async handler() {
3977
3992
  let { future } = ctx.reactRouterConfig;
3978
- if (future.v8_viteEnvironmentApi ? this.environment.name === "client" : !viteConfigEnv.isSsrBuild) {
3993
+ if (future.v8_viteEnvironmentApi ? !isReactRouterServerEnvironment(ctx, this.environment.name) : !viteConfigEnv.isSsrBuild) {
3979
3994
  return;
3980
3995
  }
3981
3996
  invariant(viteConfig);
@@ -6152,6 +6167,13 @@ if (import.meta.hot) {
6152
6167
  }
6153
6168
  };
6154
6169
  }
6170
+ function createClientRouteModuleForOptimizeDepsScan(code) {
6171
+ const ast = import_parser.parse(code, {
6172
+ sourceType: "module"
6173
+ });
6174
+ removeExports(ast, SERVER_ROUTE_EXPORTS);
6175
+ return generate(ast);
6176
+ }
6155
6177
  function createId(id, type, value) {
6156
6178
  let [base, ...rest] = id.split("?");
6157
6179
  const searchParams = new URLSearchParams(rest.join("?"));
@@ -6408,6 +6430,15 @@ ${errors.map((x) => ` - ${x}`).join("\n")}
6408
6430
  reactRouterConfig: config
6409
6431
  });
6410
6432
  let viteNormalizePath = (await import("vite")).normalizePath;
6433
+ let optimizeDepsEntries = getOptimizeDepsEntries({
6434
+ entryClientFilePath: entries.client,
6435
+ reactRouterConfig: config
6436
+ });
6437
+ let routeFiles = new Set(
6438
+ Object.values(config.routes).map(
6439
+ (route) => resolveRelativeRouteFilePath(route, config)
6440
+ )
6441
+ );
6411
6442
  return {
6412
6443
  resolve: {
6413
6444
  dedupe: [
@@ -6430,15 +6461,18 @@ ${errors.map((x) => ` - ${x}`).join("\n")}
6430
6461
  ]
6431
6462
  },
6432
6463
  optimizeDeps: {
6433
- entries: getOptimizeDepsEntries({
6434
- entryClientFilePath: entries.client,
6435
- reactRouterConfig: config
6436
- }),
6464
+ entries: optimizeDepsEntries,
6437
6465
  ...defineOptimizeDepsCompilerOptions({
6438
6466
  rolldown: {
6439
6467
  transform: {
6440
6468
  jsx: "react-jsx"
6441
- }
6469
+ },
6470
+ plugins: config.future.unstable_optimizeDeps ? [
6471
+ createRSCOptimizeDepsRouteModulesPlugin({
6472
+ routeFiles,
6473
+ transformToJs
6474
+ })
6475
+ ] : []
6442
6476
  },
6443
6477
  esbuild: {
6444
6478
  jsx: "automatic"
@@ -6889,6 +6923,32 @@ function invalidateVirtualModules2(viteDevServer) {
6889
6923
  function getRootDirectory(viteUserConfig) {
6890
6924
  return viteUserConfig.root ?? process.env.REACT_ROUTER_ROOT ?? process.cwd();
6891
6925
  }
6926
+ var jsRouteModuleRE = /\.[cm]?[jt]sx?$/;
6927
+ function createRSCOptimizeDepsRouteModulesPlugin({
6928
+ routeFiles,
6929
+ transformToJs
6930
+ }) {
6931
+ return {
6932
+ name: "react-router:rsc-optimize-deps-route-modules",
6933
+ transform: {
6934
+ filter: { id: jsRouteModuleRE },
6935
+ async handler(code, id) {
6936
+ let filename2 = id.split("?")[0];
6937
+ let normalizedFilename = getVite().normalizePath(filename2);
6938
+ if (!routeFiles.has(normalizedFilename)) {
6939
+ return;
6940
+ }
6941
+ let js2 = await transformToJs(code, filename2);
6942
+ let generated = createClientRouteModuleForOptimizeDepsScan(js2);
6943
+ return {
6944
+ code: generated.code,
6945
+ map: null,
6946
+ moduleType: "js"
6947
+ };
6948
+ }
6949
+ }
6950
+ };
6951
+ }
6892
6952
  var getClientBuildDirectory2 = (reactRouterConfig) => import_pathe6.default.join(reactRouterConfig.buildDirectory, "client");
6893
6953
  function getPrerenderConcurrencyConfig2(reactRouterConfig) {
6894
6954
  let concurrency = 1;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@react-router/dev",
3
- "version": "7.16.0",
3
+ "version": "7.18.0",
4
4
  "description": "Dev tools and CLI for React Router",
5
5
  "homepage": "https://reactrouter.com",
6
6
  "bugs": {
@@ -92,7 +92,7 @@
92
92
  "tinyglobby": "^0.2.14",
93
93
  "valibot": "^1.2.0",
94
94
  "vite-node": "^3.2.2",
95
- "@react-router/node": "7.16.0"
95
+ "@react-router/node": "7.18.0"
96
96
  },
97
97
  "devDependencies": {
98
98
  "@types/babel__core": "^7.20.5",
@@ -116,8 +116,8 @@
116
116
  "vite": "^6.3.0",
117
117
  "wireit": "0.14.9",
118
118
  "wrangler": "^4.23.0",
119
- "react-router": "^7.16.0",
120
- "@react-router/serve": "7.16.0"
119
+ "@react-router/serve": "7.18.0",
120
+ "react-router": "^7.18.0"
121
121
  },
122
122
  "peerDependencies": {
123
123
  "@vitejs/plugin-rsc": "~0.5.21",
@@ -125,8 +125,8 @@
125
125
  "typescript": "^5.1.0 || ^6.0.0",
126
126
  "vite": "^5.1.0 || ^6.0.0 || ^7.0.0 || ^8.0.0",
127
127
  "wrangler": "^3.28.2 || ^4.0.0",
128
- "@react-router/serve": "^7.16.0",
129
- "react-router": "^7.16.0"
128
+ "@react-router/serve": "^7.18.0",
129
+ "react-router": "^7.18.0"
130
130
  },
131
131
  "peerDependenciesMeta": {
132
132
  "@vitejs/plugin-rsc": {