@react-router/dev 7.8.2 → 7.9.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/dist/internal.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @react-router/dev v7.8.2
2
+ * @react-router/dev v7.9.0-pre.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -45,9 +45,9 @@ __export(internal_exports, {
45
45
  module.exports = __toCommonJS(internal_exports);
46
46
 
47
47
  // vite/rsc/plugin.ts
48
- var import_plugin_rsc = __toESM(require("@vitejs/plugin-rsc"));
49
48
  var import_es_module_lexer2 = require("es-module-lexer");
50
49
  var babel = __toESM(require("@babel/core"));
50
+ var import_picocolors4 = __toESM(require("picocolors"));
51
51
 
52
52
  // vite/virtual-module.ts
53
53
  function create(name) {
@@ -247,7 +247,7 @@ function validateRouteConfig({
247
247
  `Route config in "${routeConfigFile}" is invalid.`,
248
248
  root ? `${root}` : [],
249
249
  nested ? Object.entries(nested).map(
250
- ([path5, message]) => `Path: routes.${path5}
250
+ ([path6, message]) => `Path: routes.${path6}
251
251
  ${message}`
252
252
  ) : []
253
253
  ].flat().join("\n\n")
@@ -344,7 +344,8 @@ async function resolveConfig({
344
344
  root,
345
345
  viteNodeContext,
346
346
  reactRouterConfigFile,
347
- skipRoutes
347
+ skipRoutes,
348
+ validateConfig
348
349
  }) {
349
350
  let reactRouterUserConfig = {};
350
351
  if (reactRouterConfigFile) {
@@ -362,6 +363,12 @@ async function resolveConfig({
362
363
  return err(`${reactRouterConfigFile} must export a config`);
363
364
  }
364
365
  reactRouterUserConfig = configModule.default;
366
+ if (validateConfig) {
367
+ const error = validateConfig(reactRouterUserConfig);
368
+ if (error) {
369
+ return err(error);
370
+ }
371
+ }
365
372
  } catch (error) {
366
373
  return err(`Error loading ${reactRouterConfigFile}: ${error}`);
367
374
  }
@@ -510,7 +517,7 @@ async function resolveConfig({
510
517
  }
511
518
  }
512
519
  let future = {
513
- unstable_middleware: reactRouterUserConfig.future?.unstable_middleware ?? false,
520
+ v8_middleware: reactRouterUserConfig.future?.v8_middleware ?? false,
514
521
  unstable_optimizeDeps: reactRouterUserConfig.future?.unstable_optimizeDeps ?? false,
515
522
  unstable_splitRouteModules: reactRouterUserConfig.future?.unstable_splitRouteModules ?? false,
516
523
  unstable_subResourceIntegrity: reactRouterUserConfig.future?.unstable_subResourceIntegrity ?? false,
@@ -540,7 +547,8 @@ async function createConfigLoader({
540
547
  rootDirectory: root,
541
548
  watch: watch2,
542
549
  mode,
543
- skipRoutes
550
+ skipRoutes,
551
+ validateConfig
544
552
  }) {
545
553
  root = import_pathe3.default.normalize(root ?? process.env.REACT_ROUTER_ROOT ?? process.cwd());
546
554
  let vite2 = await import("vite");
@@ -559,7 +567,13 @@ async function createConfigLoader({
559
567
  });
560
568
  };
561
569
  updateReactRouterConfigFile();
562
- let getConfig = () => resolveConfig({ root, viteNodeContext, reactRouterConfigFile, skipRoutes });
570
+ let getConfig = () => resolveConfig({
571
+ root,
572
+ viteNodeContext,
573
+ reactRouterConfigFile,
574
+ skipRoutes,
575
+ validateConfig
576
+ });
563
577
  let appDirectory;
564
578
  let initialConfigResult = await getConfig();
565
579
  if (!initialConfigResult.ok) {
@@ -581,11 +595,11 @@ async function createConfigLoader({
581
595
  if (!fsWatcher) {
582
596
  fsWatcher = import_chokidar.default.watch([root, appDirectory], {
583
597
  ignoreInitial: true,
584
- ignored: (path5) => {
585
- let dirname4 = import_pathe3.default.dirname(path5);
598
+ ignored: (path6) => {
599
+ let dirname4 = import_pathe3.default.dirname(path6);
586
600
  return !dirname4.startsWith(appDirectory) && // Ensure we're only watching files outside of the app directory
587
601
  // that are at the root level, not nested in subdirectories
588
- path5 !== root && // Watch the root directory itself
602
+ path6 !== root && // Watch the root directory itself
589
603
  dirname4 !== root;
590
604
  }
591
605
  });
@@ -785,7 +799,7 @@ function fullpath(lineage2) {
785
799
  if (lineage2.length === 1 && route?.id === "root") return "/";
786
800
  const isLayout = route && route.index !== true && route.path === void 0;
787
801
  if (isLayout) return void 0;
788
- return "/" + lineage2.map((route2) => route2.path?.replace(/^\//, "")?.replace(/\/$/, "")).filter((path5) => path5 !== void 0 && path5 !== "").join("/");
802
+ return "/" + lineage2.map((route2) => route2.path?.replace(/^\//, "")?.replace(/\/$/, "")).filter((path6) => path6 !== void 0 && path6 !== "").join("/");
789
803
  }
790
804
 
791
805
  // typegen/generate.ts
@@ -801,7 +815,7 @@ function generateFuture(ctx) {
801
815
 
802
816
  declare module "react-router" {
803
817
  interface Future {
804
- unstable_middleware: ${ctx.config.future.unstable_middleware}
818
+ middleware: ${ctx.config.future.v8_middleware}
805
819
  }
806
820
  }
807
821
  `;
@@ -941,8 +955,8 @@ function routeFilesType({
941
955
  );
942
956
  }
943
957
  function isInAppDirectory(ctx, routeFile) {
944
- const path5 = Path3.resolve(ctx.config.appDirectory, routeFile);
945
- return path5.startsWith(ctx.config.appDirectory);
958
+ const path6 = Path3.resolve(ctx.config.appDirectory, routeFile);
959
+ return path6.startsWith(ctx.config.appDirectory);
946
960
  }
947
961
  function getRouteAnnotations({
948
962
  ctx,
@@ -1023,11 +1037,11 @@ function getRouteAnnotations({
1023
1037
  export type HeadersArgs = Annotations["HeadersArgs"];
1024
1038
  export type HeadersFunction = Annotations["HeadersFunction"];
1025
1039
 
1026
- // unstable_middleware
1027
- export type unstable_MiddlewareFunction = Annotations["unstable_MiddlewareFunction"];
1040
+ // middleware
1041
+ export type MiddlewareFunction = Annotations["MiddlewareFunction"];
1028
1042
 
1029
- // unstable_clientMiddleware
1030
- export type unstable_ClientMiddlewareFunction = Annotations["unstable_ClientMiddlewareFunction"];
1043
+ // clientMiddleware
1044
+ export type ClientMiddlewareFunction = Annotations["ClientMiddlewareFunction"];
1031
1045
 
1032
1046
  // loader
1033
1047
  export type LoaderArgs = Annotations["LoaderArgs"];
@@ -1054,21 +1068,21 @@ function getRouteAnnotations({
1054
1068
  return { filename: filename2, content };
1055
1069
  }
1056
1070
  function relativeImportSource(from, to) {
1057
- let path5 = Path3.relative(Path3.dirname(from), to);
1058
- let extension = Path3.extname(path5);
1059
- path5 = Path3.join(Path3.dirname(path5), Pathe.filename(path5));
1060
- if (!path5.startsWith("../")) path5 = "./" + path5;
1071
+ let path6 = Path3.relative(Path3.dirname(from), to);
1072
+ let extension = Path3.extname(path6);
1073
+ path6 = Path3.join(Path3.dirname(path6), Pathe.filename(path6));
1074
+ if (!path6.startsWith("../")) path6 = "./" + path6;
1061
1075
  if (!extension || /\.(js|ts)x?$/.test(extension)) {
1062
1076
  extension = ".js";
1063
1077
  }
1064
- return path5 + extension;
1078
+ return path6 + extension;
1065
1079
  }
1066
1080
  function rootDirsPath(ctx, typesPath) {
1067
1081
  const rel = Path3.relative(typesDirectory(ctx), typesPath);
1068
1082
  return Path3.join(ctx.rootDirectory, rel);
1069
1083
  }
1070
- function paramsType(path5) {
1071
- const params = parse2(path5);
1084
+ function paramsType(path6) {
1085
+ const params = parse2(path6);
1072
1086
  return t2.tsTypeLiteral(
1073
1087
  Object.entries(params).map(([param, isRequired]) => {
1074
1088
  const property = t2.tsPropertySignature(
@@ -1159,10 +1173,58 @@ async function watch(rootDirectory, { mode, logger }) {
1159
1173
  // vite/rsc/plugin.ts
1160
1174
  var import_fs = require("fs");
1161
1175
  var import_promises2 = require("fs/promises");
1162
- var import_pathe5 = __toESM(require("pathe"));
1176
+ var import_pathe6 = __toESM(require("pathe"));
1163
1177
 
1164
- // vite/rsc/virtual-route-config.ts
1178
+ // vite/has-dependency.ts
1179
+ function hasDependency({
1180
+ name,
1181
+ rootDirectory
1182
+ }) {
1183
+ try {
1184
+ return Boolean(require.resolve(name, { paths: [rootDirectory] }));
1185
+ } catch (err2) {
1186
+ return false;
1187
+ }
1188
+ }
1189
+
1190
+ // vite/optimize-deps-entries.ts
1191
+ var import_tinyglobby = require("tinyglobby");
1192
+
1193
+ // vite/resolve-relative-route-file-path.ts
1165
1194
  var import_pathe4 = __toESM(require("pathe"));
1195
+ function resolveRelativeRouteFilePath(route, reactRouterConfig) {
1196
+ let vite2 = getVite();
1197
+ let file = route.file;
1198
+ let fullPath = import_pathe4.default.resolve(reactRouterConfig.appDirectory, file);
1199
+ return vite2.normalizePath(fullPath);
1200
+ }
1201
+
1202
+ // vite/optimize-deps-entries.ts
1203
+ function getOptimizeDepsEntries({
1204
+ entryClientFilePath,
1205
+ reactRouterConfig
1206
+ }) {
1207
+ if (!reactRouterConfig.future.unstable_optimizeDeps) {
1208
+ return [];
1209
+ }
1210
+ const vite2 = getVite();
1211
+ const viteMajorVersion = parseInt(vite2.version.split(".")[0], 10);
1212
+ return [
1213
+ vite2.normalizePath(entryClientFilePath),
1214
+ ...Object.values(reactRouterConfig.routes).map(
1215
+ (route) => resolveRelativeRouteFilePath(route, reactRouterConfig)
1216
+ )
1217
+ ].map(
1218
+ (entry) => (
1219
+ // In Vite 7, the `optimizeDeps.entries` option only accepts glob patterns.
1220
+ // In prior versions, absolute file paths were treated differently.
1221
+ viteMajorVersion >= 7 ? (0, import_tinyglobby.escapePath)(entry) : entry
1222
+ )
1223
+ );
1224
+ }
1225
+
1226
+ // vite/rsc/virtual-route-config.ts
1227
+ var import_pathe5 = __toESM(require("pathe"));
1166
1228
  function createVirtualRouteConfig({
1167
1229
  appDirectory,
1168
1230
  routeConfig
@@ -1181,7 +1243,7 @@ function createVirtualRouteConfig({
1181
1243
  continue;
1182
1244
  }
1183
1245
  code += "{";
1184
- const routeFile = import_pathe4.default.resolve(appDirectory, route.file);
1246
+ const routeFile = import_pathe5.default.resolve(appDirectory, route.file);
1185
1247
  const routeId = route.id || createRouteId2(route.file, appDirectory);
1186
1248
  routeIdByFile.set(routeFile, routeId);
1187
1249
  code += `lazy: () => import(${JSON.stringify(
@@ -1209,7 +1271,7 @@ function createVirtualRouteConfig({
1209
1271
  return { code, routeIdByFile };
1210
1272
  }
1211
1273
  function createRouteId2(file, appDirectory) {
1212
- return import_pathe4.default.relative(appDirectory, file).replace(/\\+/, "/").slice(0, -import_pathe4.default.extname(file).length);
1274
+ return import_pathe5.default.relative(appDirectory, file).replace(/\\+/, "/").slice(0, -import_pathe5.default.extname(file).length);
1213
1275
  }
1214
1276
 
1215
1277
  // vite/rsc/virtual-route-modules.ts
@@ -1223,10 +1285,10 @@ var removeExports = (ast, exportsToRemove) => {
1223
1285
  let markedForRemoval = /* @__PURE__ */ new Set();
1224
1286
  let removedExportLocalNames = /* @__PURE__ */ new Set();
1225
1287
  traverse(ast, {
1226
- ExportDeclaration(path5) {
1227
- if (path5.node.type === "ExportNamedDeclaration") {
1228
- if (path5.node.specifiers.length) {
1229
- path5.node.specifiers = path5.node.specifiers.filter((specifier) => {
1288
+ ExportDeclaration(path6) {
1289
+ if (path6.node.type === "ExportNamedDeclaration") {
1290
+ if (path6.node.specifiers.length) {
1291
+ path6.node.specifiers = path6.node.specifiers.filter((specifier) => {
1230
1292
  if (specifier.type === "ExportSpecifier" && specifier.exported.type === "Identifier") {
1231
1293
  if (exportsToRemove.includes(specifier.exported.name)) {
1232
1294
  exportsFiltered = true;
@@ -1238,12 +1300,12 @@ var removeExports = (ast, exportsToRemove) => {
1238
1300
  }
1239
1301
  return true;
1240
1302
  });
1241
- if (path5.node.specifiers.length === 0) {
1242
- markedForRemoval.add(path5);
1303
+ if (path6.node.specifiers.length === 0) {
1304
+ markedForRemoval.add(path6);
1243
1305
  }
1244
1306
  }
1245
- if (path5.node.declaration?.type === "VariableDeclaration") {
1246
- let declaration = path5.node.declaration;
1307
+ if (path6.node.declaration?.type === "VariableDeclaration") {
1308
+ let declaration = path6.node.declaration;
1247
1309
  declaration.declarations = declaration.declarations.filter(
1248
1310
  (declaration2) => {
1249
1311
  if (declaration2.id.type === "Identifier" && exportsToRemove.includes(declaration2.id.name)) {
@@ -1257,30 +1319,30 @@ var removeExports = (ast, exportsToRemove) => {
1257
1319
  }
1258
1320
  );
1259
1321
  if (declaration.declarations.length === 0) {
1260
- markedForRemoval.add(path5);
1322
+ markedForRemoval.add(path6);
1261
1323
  }
1262
1324
  }
1263
- if (path5.node.declaration?.type === "FunctionDeclaration") {
1264
- let id = path5.node.declaration.id;
1325
+ if (path6.node.declaration?.type === "FunctionDeclaration") {
1326
+ let id = path6.node.declaration.id;
1265
1327
  if (id && exportsToRemove.includes(id.name)) {
1266
- markedForRemoval.add(path5);
1328
+ markedForRemoval.add(path6);
1267
1329
  }
1268
1330
  }
1269
- if (path5.node.declaration?.type === "ClassDeclaration") {
1270
- let id = path5.node.declaration.id;
1331
+ if (path6.node.declaration?.type === "ClassDeclaration") {
1332
+ let id = path6.node.declaration.id;
1271
1333
  if (id && exportsToRemove.includes(id.name)) {
1272
- markedForRemoval.add(path5);
1334
+ markedForRemoval.add(path6);
1273
1335
  }
1274
1336
  }
1275
1337
  }
1276
- if (path5.node.type === "ExportDefaultDeclaration") {
1338
+ if (path6.node.type === "ExportDefaultDeclaration") {
1277
1339
  if (exportsToRemove.includes("default")) {
1278
- markedForRemoval.add(path5);
1279
- if (path5.node.declaration) {
1280
- if (path5.node.declaration.type === "Identifier") {
1281
- removedExportLocalNames.add(path5.node.declaration.name);
1282
- } else if ((path5.node.declaration.type === "FunctionDeclaration" || path5.node.declaration.type === "ClassDeclaration") && path5.node.declaration.id) {
1283
- removedExportLocalNames.add(path5.node.declaration.id.name);
1340
+ markedForRemoval.add(path6);
1341
+ if (path6.node.declaration) {
1342
+ if (path6.node.declaration.type === "Identifier") {
1343
+ removedExportLocalNames.add(path6.node.declaration.name);
1344
+ } else if ((path6.node.declaration.type === "FunctionDeclaration" || path6.node.declaration.type === "ClassDeclaration") && path6.node.declaration.id) {
1345
+ removedExportLocalNames.add(path6.node.declaration.id.name);
1284
1346
  }
1285
1347
  }
1286
1348
  }
@@ -1288,21 +1350,21 @@ var removeExports = (ast, exportsToRemove) => {
1288
1350
  }
1289
1351
  });
1290
1352
  traverse(ast, {
1291
- ExpressionStatement(path5) {
1292
- if (!path5.parentPath.isProgram()) {
1353
+ ExpressionStatement(path6) {
1354
+ if (!path6.parentPath.isProgram()) {
1293
1355
  return;
1294
1356
  }
1295
- if (path5.node.expression.type === "AssignmentExpression") {
1296
- const left = path5.node.expression.left;
1357
+ if (path6.node.expression.type === "AssignmentExpression") {
1358
+ const left = path6.node.expression.left;
1297
1359
  if (left.type === "MemberExpression" && left.object.type === "Identifier" && (exportsToRemove.includes(left.object.name) || removedExportLocalNames.has(left.object.name))) {
1298
- markedForRemoval.add(path5);
1360
+ markedForRemoval.add(path6);
1299
1361
  }
1300
1362
  }
1301
1363
  }
1302
1364
  });
1303
1365
  if (markedForRemoval.size > 0 || exportsFiltered) {
1304
- for (let path5 of markedForRemoval) {
1305
- path5.remove();
1366
+ for (let path6 of markedForRemoval) {
1367
+ path6.remove();
1306
1368
  }
1307
1369
  (0, import_babel_dead_code_elimination.deadCodeElimination)(ast, previouslyReferencedIdentifiers);
1308
1370
  }
@@ -1353,7 +1415,7 @@ var SERVER_ONLY_ROUTE_EXPORTS = [
1353
1415
  ...SERVER_ONLY_COMPONENT_EXPORTS,
1354
1416
  "loader",
1355
1417
  "action",
1356
- "unstable_middleware",
1418
+ "middleware",
1357
1419
  "headers"
1358
1420
  ];
1359
1421
  var SERVER_ONLY_ROUTE_EXPORTS_SET = new Set(SERVER_ONLY_ROUTE_EXPORTS);
@@ -1384,7 +1446,7 @@ var CLIENT_COMPONENT_EXPORTS = [
1384
1446
  var CLIENT_NON_COMPONENT_EXPORTS = [
1385
1447
  "clientAction",
1386
1448
  "clientLoader",
1387
- "unstable_clientMiddleware",
1449
+ "clientMiddleware",
1388
1450
  "handle",
1389
1451
  "meta",
1390
1452
  "links",
@@ -1618,16 +1680,57 @@ function validatePluginOrder() {
1618
1680
  (plugin) => pluginName.includes(plugin.name)
1619
1681
  );
1620
1682
  };
1621
- let rollupPrePlugins = [
1622
- { pluginName: "@mdx-js/rollup", displayName: "@mdx-js/rollup" }
1623
- ];
1624
- for (let prePlugin of rollupPrePlugins) {
1625
- let prePluginIndex = pluginIndex(prePlugin.pluginName);
1626
- if (prePluginIndex >= 0 && prePluginIndex > pluginIndex(["react-router", "react-router/rsc"])) {
1627
- throw new Error(
1628
- `The "${prePlugin.displayName}" plugin should be placed before the React Router plugin in your Vite config file`
1629
- );
1630
- }
1683
+ let reactRouterRscPluginIndex = pluginIndex("react-router/rsc");
1684
+ let viteRscPluginIndex = pluginIndex("rsc");
1685
+ if (reactRouterRscPluginIndex >= 0 && viteRscPluginIndex >= 0 && reactRouterRscPluginIndex > viteRscPluginIndex) {
1686
+ throw new Error(
1687
+ `The "@vitejs/plugin-rsc" plugin should be placed after the React Router RSC plugin in your Vite config`
1688
+ );
1689
+ }
1690
+ let reactRouterPluginIndex = pluginIndex([
1691
+ "react-router",
1692
+ "react-router/rsc"
1693
+ ]);
1694
+ let mdxPluginIndex = pluginIndex("@mdx-js/rollup");
1695
+ if (mdxPluginIndex >= 0 && mdxPluginIndex > reactRouterPluginIndex) {
1696
+ throw new Error(
1697
+ `The "@mdx-js/rollup" plugin should be placed before the React Router plugin in your Vite config`
1698
+ );
1699
+ }
1700
+ }
1701
+ };
1702
+ }
1703
+
1704
+ // vite/plugins/warn-on-client-source-maps.ts
1705
+ var import_picocolors3 = __toESM(require("picocolors"));
1706
+ function warnOnClientSourceMaps() {
1707
+ let viteConfig;
1708
+ let viteCommand;
1709
+ let logged = false;
1710
+ return {
1711
+ name: "react-router:warn-on-client-source-maps",
1712
+ config(_, configEnv) {
1713
+ viteCommand = configEnv.command;
1714
+ },
1715
+ configResolved(config) {
1716
+ viteConfig = config;
1717
+ },
1718
+ buildStart() {
1719
+ invariant(viteConfig);
1720
+ if (!logged && viteCommand === "build" && viteConfig.mode === "production" && !viteConfig.build.ssr && (viteConfig.build.sourcemap || viteConfig.environments?.client?.build.sourcemap)) {
1721
+ viteConfig.logger.warn(
1722
+ import_picocolors3.default.yellow(
1723
+ "\n" + import_picocolors3.default.bold(" \u26A0\uFE0F Source maps are enabled in production\n") + [
1724
+ "This makes your server code publicly",
1725
+ "visible in the browser. This is highly",
1726
+ "discouraged! If you insist, ensure that",
1727
+ "you are using environment variables for",
1728
+ "secrets and not hard-coding them in",
1729
+ "your source code."
1730
+ ].map((line) => " " + line).join("\n") + "\n"
1731
+ )
1732
+ );
1733
+ logged = true;
1631
1734
  }
1632
1735
  }
1633
1736
  };
@@ -1640,18 +1743,56 @@ function reactRouterRSCVitePlugin() {
1640
1743
  let typegenWatcherPromise;
1641
1744
  let viteCommand;
1642
1745
  let routeIdByFile;
1746
+ let logger;
1747
+ const defaultEntries = getDefaultEntries();
1643
1748
  return [
1644
1749
  {
1645
1750
  name: "react-router/rsc",
1646
1751
  async config(viteUserConfig, { command, mode }) {
1647
1752
  await import_es_module_lexer2.init;
1753
+ await preloadVite();
1648
1754
  viteCommand = command;
1649
1755
  const rootDirectory = getRootDirectory(viteUserConfig);
1650
1756
  const watch2 = command === "serve";
1651
- configLoader = await createConfigLoader({ rootDirectory, mode, watch: watch2 });
1757
+ configLoader = await createConfigLoader({
1758
+ rootDirectory,
1759
+ mode,
1760
+ watch: watch2,
1761
+ validateConfig: (userConfig) => {
1762
+ let errors = [];
1763
+ if (userConfig.buildEnd) errors.push("buildEnd");
1764
+ if (userConfig.prerender) errors.push("prerender");
1765
+ if (userConfig.presets?.length) errors.push("presets");
1766
+ if (userConfig.routeDiscovery) errors.push("routeDiscovery");
1767
+ if (userConfig.serverBundles) errors.push("serverBundles");
1768
+ if (userConfig.ssr === false) errors.push("ssr: false");
1769
+ if (userConfig.future?.unstable_splitRouteModules)
1770
+ errors.push("future.unstable_splitRouteModules");
1771
+ if (userConfig.future?.unstable_viteEnvironmentApi === false)
1772
+ errors.push("future.unstable_viteEnvironmentApi: false");
1773
+ if (userConfig.future?.v8_middleware === false)
1774
+ errors.push("future.v8_middleware: false");
1775
+ if (userConfig.future?.unstable_subResourceIntegrity)
1776
+ errors.push("future.unstable_subResourceIntegrity");
1777
+ if (errors.length) {
1778
+ return `RSC Framework Mode does not currently support the following React Router config:
1779
+ ${errors.map((x) => ` - ${x}`).join("\n")}
1780
+ `;
1781
+ }
1782
+ }
1783
+ });
1652
1784
  const configResult = await configLoader.getConfig();
1653
1785
  if (!configResult.ok) throw new Error(configResult.error);
1654
1786
  config = configResult.value;
1787
+ if (viteUserConfig.base && config.basename !== "/" && viteCommand === "serve" && !viteUserConfig.server?.middlewareMode && !config.basename.startsWith(viteUserConfig.base)) {
1788
+ throw new Error(
1789
+ "When using the React Router `basename` and the Vite `base` config, the `basename` config must begin with `base` for the default Vite dev server."
1790
+ );
1791
+ }
1792
+ const vite2 = await import("vite");
1793
+ logger = vite2.createLogger(viteUserConfig.logLevel, {
1794
+ prefix: "[react-router]"
1795
+ });
1655
1796
  return {
1656
1797
  resolve: {
1657
1798
  dedupe: [
@@ -1662,10 +1803,14 @@ function reactRouterRSCVitePlugin() {
1662
1803
  // You must render this element inside a <Remix> element`.
1663
1804
  "react-router",
1664
1805
  "react-router/dom",
1665
- "react-router-dom"
1806
+ ...hasDependency({ name: "react-router-dom", rootDirectory }) ? ["react-router-dom"] : []
1666
1807
  ]
1667
1808
  },
1668
1809
  optimizeDeps: {
1810
+ entries: getOptimizeDepsEntries({
1811
+ entryClientFilePath: defaultEntries.client,
1812
+ reactRouterConfig: config
1813
+ }),
1669
1814
  esbuildOptions: {
1670
1815
  jsx: "automatic"
1671
1816
  },
@@ -1677,7 +1822,8 @@ function reactRouterRSCVitePlugin() {
1677
1822
  "react/jsx-runtime",
1678
1823
  "react/jsx-dev-runtime",
1679
1824
  "react-dom",
1680
- "react-dom/client"
1825
+ "react-dom/client",
1826
+ "react-router/internal/react-server-client"
1681
1827
  ]
1682
1828
  },
1683
1829
  esbuild: {
@@ -1687,17 +1833,47 @@ function reactRouterRSCVitePlugin() {
1687
1833
  environments: {
1688
1834
  client: {
1689
1835
  build: {
1690
- outDir: (0, import_pathe5.join)(config.buildDirectory, "client")
1836
+ rollupOptions: {
1837
+ input: {
1838
+ index: defaultEntries.client
1839
+ }
1840
+ },
1841
+ outDir: (0, import_pathe6.join)(config.buildDirectory, "client")
1691
1842
  }
1692
1843
  },
1693
1844
  rsc: {
1694
1845
  build: {
1695
- outDir: (0, import_pathe5.join)(config.buildDirectory, "server")
1846
+ rollupOptions: {
1847
+ input: {
1848
+ // We use a virtual entry here so that consumers can import
1849
+ // it as `virtual:react-router/unstable_rsc/rsc-entry`
1850
+ // without needing to know the actual file path, which is
1851
+ // important when using the default entries.
1852
+ index: defaultEntries.rsc
1853
+ },
1854
+ output: {
1855
+ entryFileNames: config.serverBuildFile,
1856
+ format: config.serverModuleFormat
1857
+ }
1858
+ },
1859
+ outDir: (0, import_pathe6.join)(config.buildDirectory, "server")
1696
1860
  }
1697
1861
  },
1698
1862
  ssr: {
1699
1863
  build: {
1700
- outDir: (0, import_pathe5.join)(config.buildDirectory, "server/__ssr_build")
1864
+ rollupOptions: {
1865
+ input: {
1866
+ index: defaultEntries.ssr
1867
+ },
1868
+ output: {
1869
+ // Note: We don't set `entryFileNames` here because it's
1870
+ // considered private to the RSC environment build, and
1871
+ // @vitejs/plugin-rsc currently breaks if it's set to
1872
+ // something other than `index.js`.
1873
+ format: config.serverModuleFormat
1874
+ }
1875
+ },
1876
+ outDir: (0, import_pathe6.join)(config.buildDirectory, "server/__ssr_build")
1701
1877
  }
1702
1878
  }
1703
1879
  },
@@ -1724,6 +1900,35 @@ function reactRouterRSCVitePlugin() {
1724
1900
  }
1725
1901
  };
1726
1902
  },
1903
+ async configureServer(viteDevServer) {
1904
+ configLoader.onChange(
1905
+ async ({
1906
+ result,
1907
+ configCodeChanged,
1908
+ routeConfigCodeChanged,
1909
+ configChanged,
1910
+ routeConfigChanged
1911
+ }) => {
1912
+ if (!result.ok) {
1913
+ invalidateVirtualModules(viteDevServer);
1914
+ logger.error(result.error, {
1915
+ clear: true,
1916
+ timestamp: true
1917
+ });
1918
+ return;
1919
+ }
1920
+ let message = configChanged ? "Config changed." : routeConfigChanged ? "Route config changed." : configCodeChanged ? "Config saved." : routeConfigCodeChanged ? " Route config saved." : "Config saved";
1921
+ logger.info(import_picocolors4.default.green(message), {
1922
+ clear: true,
1923
+ timestamp: true
1924
+ });
1925
+ config = result.value;
1926
+ if (configChanged || routeConfigChanged) {
1927
+ invalidateVirtualModules(viteDevServer);
1928
+ }
1929
+ }
1930
+ );
1931
+ },
1727
1932
  async buildEnd() {
1728
1933
  await configLoader.close();
1729
1934
  }
@@ -1750,6 +1955,12 @@ function reactRouterRSCVitePlugin() {
1750
1955
  (await typegenWatcherPromise)?.close();
1751
1956
  }
1752
1957
  },
1958
+ {
1959
+ name: "react-router/rsc/virtual-rsc-entry",
1960
+ resolveId(id) {
1961
+ if (id === virtual.rscEntry.id) return defaultEntries.rsc;
1962
+ }
1963
+ },
1753
1964
  {
1754
1965
  name: "react-router/rsc/virtual-route-config",
1755
1966
  resolveId(id) {
@@ -1781,6 +1992,19 @@ function reactRouterRSCVitePlugin() {
1781
1992
  });
1782
1993
  }
1783
1994
  },
1995
+ {
1996
+ name: "react-router/rsc/virtual-basename",
1997
+ resolveId(id) {
1998
+ if (id === virtual.basename.id) {
1999
+ return virtual.basename.resolvedId;
2000
+ }
2001
+ },
2002
+ load(id) {
2003
+ if (id === virtual.basename.resolvedId) {
2004
+ return `export default ${JSON.stringify(config.basename)};`;
2005
+ }
2006
+ }
2007
+ },
1784
2008
  {
1785
2009
  name: "react-router/rsc/hmr/inject-runtime",
1786
2010
  enforce: "pre",
@@ -1808,10 +2032,10 @@ function reactRouterRSCVitePlugin() {
1808
2032
  },
1809
2033
  async load(id) {
1810
2034
  if (id !== virtual.hmrRuntime.resolvedId) return;
1811
- const reactRefreshDir = import_pathe5.default.dirname(
2035
+ const reactRefreshDir = import_pathe6.default.dirname(
1812
2036
  require.resolve("react-refresh/package.json")
1813
2037
  );
1814
- const reactRefreshRuntimePath = import_pathe5.default.join(
2038
+ const reactRefreshRuntimePath = import_pathe6.default.join(
1815
2039
  reactRefreshDir,
1816
2040
  "cjs/react-refresh-runtime.development.js"
1817
2041
  );
@@ -1868,10 +2092,16 @@ function reactRouterRSCVitePlugin() {
1868
2092
  name: "react-router/rsc/hmr/updates",
1869
2093
  async hotUpdate({ server, file, modules }) {
1870
2094
  if (this.environment.name !== "rsc") return;
1871
- const isServerOnlyChange = (server.environments.client.moduleGraph.getModulesByFile(file)?.size ?? 0) === 0;
2095
+ const clientModules = server.environments.client.moduleGraph.getModulesByFile(file);
2096
+ const vite2 = await import("vite");
2097
+ const isServerOnlyChange = !clientModules || clientModules.size === 0 || // Handle CSS injected from server-first routes (with ?direct query
2098
+ // string) since the client graph has a reference to the CSS
2099
+ vite2.isCSSRequest(file) && Array.from(clientModules).some(
2100
+ (mod) => mod.id?.includes("?direct")
2101
+ );
1872
2102
  for (const mod of getModulesWithImporters(modules)) {
1873
2103
  if (!mod.file) continue;
1874
- const normalizedPath = import_pathe5.default.normalize(mod.file);
2104
+ const normalizedPath = import_pathe6.default.normalize(mod.file);
1875
2105
  const routeId = routeIdByFile?.get(normalizedPath);
1876
2106
  if (routeId !== void 0) {
1877
2107
  const routeSource = await (0, import_promises2.readFile)(normalizedPath, "utf8");
@@ -1902,44 +2132,56 @@ function reactRouterRSCVitePlugin() {
1902
2132
  }
1903
2133
  },
1904
2134
  validatePluginOrder(),
1905
- (0, import_plugin_rsc.default)({ entries: getRscEntries() })
2135
+ warnOnClientSourceMaps()
1906
2136
  ];
1907
2137
  }
1908
2138
  var virtual = {
1909
2139
  routeConfig: create("unstable_rsc/routes"),
1910
2140
  injectHmrRuntime: create("unstable_rsc/inject-hmr-runtime"),
1911
- hmrRuntime: create("unstable_rsc/runtime")
2141
+ hmrRuntime: create("unstable_rsc/runtime"),
2142
+ basename: create("unstable_rsc/basename"),
2143
+ rscEntry: create("unstable_rsc/rsc-entry")
1912
2144
  };
2145
+ function invalidateVirtualModules(viteDevServer) {
2146
+ for (const vmod of Object.values(virtual)) {
2147
+ for (const env of Object.values(viteDevServer.environments)) {
2148
+ const mod = env.moduleGraph.getModuleById(vmod.resolvedId);
2149
+ if (mod) {
2150
+ env.moduleGraph.invalidateModule(mod);
2151
+ }
2152
+ }
2153
+ }
2154
+ }
1913
2155
  function getRootDirectory(viteUserConfig) {
1914
2156
  return viteUserConfig.root ?? process.env.REACT_ROUTER_ROOT ?? process.cwd();
1915
2157
  }
1916
- function getRscEntries() {
1917
- const entriesDir = (0, import_pathe5.join)(
1918
- getDevPackageRoot(),
1919
- "dist",
1920
- "config",
1921
- "default-rsc-entries"
1922
- );
1923
- return {
1924
- client: (0, import_pathe5.join)(entriesDir, "entry.client.tsx"),
1925
- rsc: (0, import_pathe5.join)(entriesDir, "entry.rsc.tsx"),
1926
- ssr: (0, import_pathe5.join)(entriesDir, "entry.ssr.tsx")
1927
- };
1928
- }
1929
2158
  function getDevPackageRoot() {
1930
- const currentDir = (0, import_pathe5.dirname)(__dirname);
2159
+ const currentDir = (0, import_pathe6.dirname)(__dirname);
1931
2160
  let dir = currentDir;
1932
- while (dir !== (0, import_pathe5.dirname)(dir)) {
2161
+ while (dir !== (0, import_pathe6.dirname)(dir)) {
1933
2162
  try {
1934
- const packageJsonPath = (0, import_pathe5.join)(dir, "package.json");
2163
+ const packageJsonPath = (0, import_pathe6.join)(dir, "package.json");
1935
2164
  (0, import_fs.readFileSync)(packageJsonPath, "utf-8");
1936
2165
  return dir;
1937
2166
  } catch {
1938
- dir = (0, import_pathe5.dirname)(dir);
2167
+ dir = (0, import_pathe6.dirname)(dir);
1939
2168
  }
1940
2169
  }
1941
2170
  throw new Error("Could not find package.json");
1942
2171
  }
2172
+ function getDefaultEntries() {
2173
+ const defaultEntriesDir = (0, import_pathe6.join)(
2174
+ getDevPackageRoot(),
2175
+ "dist",
2176
+ "config",
2177
+ "default-rsc-entries"
2178
+ );
2179
+ return {
2180
+ rsc: (0, import_pathe6.join)(defaultEntriesDir, "entry.rsc.tsx"),
2181
+ ssr: (0, import_pathe6.join)(defaultEntriesDir, "entry.ssr.tsx"),
2182
+ client: (0, import_pathe6.join)(defaultEntriesDir, "entry.client.tsx")
2183
+ };
2184
+ }
1943
2185
  function getModulesWithImporters(modules) {
1944
2186
  const visited = /* @__PURE__ */ new Set();
1945
2187
  const result = /* @__PURE__ */ new Set();