@react-router/dev 7.2.0 → 7.3.0-pre.1

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/vite.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @react-router/dev v7.2.0
2
+ * @react-router/dev v7.3.0-pre.1
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -117,27 +117,46 @@ function getVite() {
117
117
  return vite;
118
118
  }
119
119
 
120
+ // vite/ssr-externals.ts
121
+ var ssrExternals = isReactRouterRepo() ? [
122
+ // This is only needed within this repo because these packages
123
+ // are linked to a directory outside of node_modules so Vite
124
+ // treats them as internal code by default.
125
+ "react-router",
126
+ "react-router-dom",
127
+ "@react-router/architect",
128
+ "@react-router/cloudflare",
129
+ "@react-router/dev",
130
+ "@react-router/express",
131
+ "@react-router/node",
132
+ "@react-router/serve"
133
+ ] : void 0;
134
+
120
135
  // vite/vite-node.ts
121
- async function createContext(viteConfig = {}) {
136
+ async function createContext({
137
+ root,
138
+ mode
139
+ }) {
122
140
  await preloadVite();
123
141
  const vite2 = getVite();
124
- const devServer = await vite2.createServer(
125
- vite2.mergeConfig(
126
- {
127
- server: {
128
- preTransformRequests: false,
129
- hmr: false
130
- },
131
- optimizeDeps: {
132
- noDiscovery: true
133
- },
134
- configFile: false,
135
- envFile: false,
136
- plugins: []
137
- },
138
- viteConfig
139
- )
140
- );
142
+ const devServer = await vite2.createServer({
143
+ root,
144
+ mode,
145
+ server: {
146
+ preTransformRequests: false,
147
+ hmr: false,
148
+ watch: null
149
+ },
150
+ ssr: {
151
+ external: ssrExternals
152
+ },
153
+ optimizeDeps: {
154
+ noDiscovery: true
155
+ },
156
+ configFile: false,
157
+ envFile: false,
158
+ plugins: []
159
+ });
141
160
  await devServer.pluginContainer.buildStart({});
142
161
  const server = new import_server.ViteNodeServer(devServer);
143
162
  (0, import_source_map.installSourcemapsSupport)({
@@ -453,6 +472,7 @@ async function resolveConfig({
453
472
  );
454
473
  }
455
474
  let future = {
475
+ unstable_middleware: reactRouterUserConfig.future?.unstable_middleware ?? false,
456
476
  unstable_optimizeDeps: reactRouterUserConfig.future?.unstable_optimizeDeps ?? false,
457
477
  unstable_splitRouteModules: reactRouterUserConfig.future?.unstable_splitRouteModules ?? false,
458
478
  unstable_viteEnvironmentApi: reactRouterUserConfig.future?.unstable_viteEnvironmentApi ?? false
@@ -482,11 +502,7 @@ async function createConfigLoader({
482
502
  root = root ?? process.env.REACT_ROUTER_ROOT ?? process.cwd();
483
503
  let viteNodeContext = await createContext({
484
504
  root,
485
- mode: watch2 ? "development" : "production",
486
- server: !watch2 ? { watch: null } : {},
487
- ssr: {
488
- external: ssrExternals
489
- }
505
+ mode: watch2 ? "development" : "production"
490
506
  });
491
507
  let reactRouterConfigFile = findEntry(root, "react-router.config", {
492
508
  absolute: true
@@ -610,19 +626,6 @@ async function resolveEntryFiles({
610
626
  let entryServerFilePath = userEntryServerFile ? import_pathe3.default.resolve(reactRouterConfig.appDirectory, userEntryServerFile) : import_pathe3.default.resolve(defaultsDirectory, entryServerFile);
611
627
  return { entryClientFilePath, entryServerFilePath };
612
628
  }
613
- var ssrExternals = isReactRouterRepo() ? [
614
- // This is only needed within this repo because these packages
615
- // are linked to a directory outside of node_modules so Vite
616
- // treats them as internal code by default.
617
- "react-router",
618
- "react-router-dom",
619
- "@react-router/architect",
620
- "@react-router/cloudflare",
621
- "@react-router/dev",
622
- "@react-router/express",
623
- "@react-router/node",
624
- "@react-router/serve"
625
- ] : void 0;
626
629
  var entryExts = [".js", ".jsx", ".ts", ".tsx"];
627
630
  function findEntry(dir, basename2, options) {
628
631
  for (let ext of entryExts) {
@@ -750,6 +753,8 @@ function generate2(ctx, route) {
750
753
  export type HeadersArgs = T.HeadersArgs
751
754
  export type HeadersFunction = (args: HeadersArgs) => Headers | HeadersInit
752
755
 
756
+ export type unstable_MiddlewareFunction = T.CreateServerMiddlewareFunction<Info>
757
+ export type unstable_ClientMiddlewareFunction = T.CreateClientMiddlewareFunction<Info>
753
758
  export type LoaderArgs = T.CreateServerLoaderArgs<Info>
754
759
  export type ClientLoaderArgs = T.CreateClientLoaderArgs<Info>
755
760
  export type ActionArgs = T.CreateServerActionArgs<Info>
@@ -832,12 +837,16 @@ function register(ctx) {
832
837
  }
833
838
  `;
834
839
  const { t: t2 } = babel_exports;
840
+ const indexPaths = new Set(
841
+ Object.values(ctx.config.routes).filter((route) => route.index).map((route) => route.path)
842
+ );
835
843
  const typeParams = t2.tsTypeAliasDeclaration(
836
844
  t2.identifier("Params"),
837
845
  null,
838
846
  t2.tsTypeLiteral(
839
847
  Object.values(ctx.config.routes).map((route) => {
840
848
  if (route.id !== "root" && !route.path) return void 0;
849
+ if (!route.index && indexPaths.has(route.path)) return void 0;
841
850
  const lineage2 = lineage(ctx.config.routes, route);
842
851
  const fullpath2 = fullpath(lineage2);
843
852
  const params = parse2(fullpath2);
@@ -867,7 +876,18 @@ var import_node_events = require("events");
867
876
  var import_node_stream = require("stream");
868
877
  var import_set_cookie_parser = require("set-cookie-parser");
869
878
  var import_node = require("@react-router/node");
870
- function fromNodeHeaders(nodeHeaders) {
879
+ function fromNodeHeaders(nodeReq) {
880
+ let nodeHeaders = nodeReq.headers;
881
+ if (nodeReq.httpVersionMajor >= 2) {
882
+ nodeHeaders = { ...nodeHeaders };
883
+ if (nodeHeaders[":authority"]) {
884
+ nodeHeaders.host = nodeHeaders[":authority"];
885
+ }
886
+ delete nodeHeaders[":authority"];
887
+ delete nodeHeaders[":method"];
888
+ delete nodeHeaders[":path"];
889
+ delete nodeHeaders[":scheme"];
890
+ }
871
891
  let headers = new Headers();
872
892
  for (let [key, values] of Object.entries(nodeHeaders)) {
873
893
  if (values) {
@@ -892,7 +912,7 @@ function fromNodeRequest(nodeReq, nodeRes) {
892
912
  let controller = new AbortController();
893
913
  let init = {
894
914
  method: nodeReq.method,
895
- headers: fromNodeHeaders(nodeReq.headers),
915
+ headers: fromNodeHeaders(nodeReq),
896
916
  signal: controller.signal
897
917
  };
898
918
  nodeRes.on("finish", () => controller = null);
@@ -963,15 +983,12 @@ var isCssUrlWithoutSideEffects = (url2) => {
963
983
  }
964
984
  return false;
965
985
  };
966
- var injectQuery = (url2, query) => url2.includes("?") ? url2.replace("?", `?${query}&`) : `${url2}?${query}`;
967
986
  var getStylesForFiles = async ({
968
987
  viteDevServer,
969
988
  rootDirectory,
970
- cssModulesManifest,
989
+ loadCssContents,
971
990
  files
972
991
  }) => {
973
- let vite2 = getVite();
974
- let viteMajor = parseInt(vite2.version.split(".")[0], 10);
975
992
  let styles = {};
976
993
  let deps = /* @__PURE__ */ new Set();
977
994
  try {
@@ -1000,21 +1017,9 @@ var getStylesForFiles = async ({
1000
1017
  for (let dep of deps) {
1001
1018
  if (dep.file && isCssFile(dep.file) && !isCssUrlWithoutSideEffects(dep.url)) {
1002
1019
  try {
1003
- let css = isCssModulesFile(dep.file) ? cssModulesManifest[dep.file] : (await viteDevServer.ssrLoadModule(
1004
- // We need the ?inline query in Vite v6 when loading CSS in SSR
1005
- // since it does not expose the default export for CSS in a
1006
- // server environment. This is to align with non-SSR
1007
- // environments. For backwards compatibility with v5 we keep
1008
- // using the URL without ?inline query because the HMR code was
1009
- // relying on the implicit SSR-client module graph relationship.
1010
- viteMajor >= 6 ? injectQuery(dep.url, "inline") : dep.url
1011
- )).default;
1012
- if (css === void 0) {
1013
- throw new Error();
1014
- }
1015
- styles[dep.url] = css;
1020
+ styles[dep.url] = await loadCssContents(viteDevServer, dep);
1016
1021
  } catch {
1017
- console.warn(`Could not load ${dep.file}`);
1022
+ console.warn(`Failed to load CSS for ${dep.file}`);
1018
1023
  }
1019
1024
  }
1020
1025
  }
@@ -1062,33 +1067,41 @@ var groupRoutesByParentId = (manifest) => {
1062
1067
  });
1063
1068
  return routes;
1064
1069
  };
1065
- var createRoutes = (manifest, parentId = "", routesByParentId = groupRoutesByParentId(manifest)) => {
1070
+ var createRoutesWithChildren = (manifest, parentId = "", routesByParentId = groupRoutesByParentId(manifest)) => {
1066
1071
  return (routesByParentId[parentId] || []).map((route) => ({
1067
1072
  ...route,
1068
- children: createRoutes(manifest, route.id, routesByParentId)
1073
+ ...route.index ? {
1074
+ index: true
1075
+ } : {
1076
+ index: false,
1077
+ children: createRoutesWithChildren(
1078
+ manifest,
1079
+ route.id,
1080
+ routesByParentId
1081
+ )
1082
+ }
1069
1083
  }));
1070
1084
  };
1071
- var getStylesForUrl = async ({
1085
+ var getStylesForPathname = async ({
1072
1086
  viteDevServer,
1073
1087
  rootDirectory,
1074
1088
  reactRouterConfig,
1075
1089
  entryClientFilePath,
1076
- cssModulesManifest,
1077
- build,
1078
- url: url2
1090
+ loadCssContents,
1091
+ pathname
1079
1092
  }) => {
1080
- if (url2 === void 0 || url2.includes("?_data=")) {
1093
+ if (pathname === void 0 || pathname.includes("?_data=")) {
1081
1094
  return void 0;
1082
1095
  }
1083
- let routes = createRoutes(build.routes);
1096
+ let routesWithChildren = createRoutesWithChildren(reactRouterConfig.routes);
1084
1097
  let appPath = path5.relative(process.cwd(), reactRouterConfig.appDirectory);
1085
- let documentRouteFiles = (0, import_react_router.matchRoutes)(routes, url2, build.basename)?.map(
1098
+ let documentRouteFiles = (0, import_react_router.matchRoutes)(routesWithChildren, pathname, reactRouterConfig.basename)?.map(
1086
1099
  (match) => path5.resolve(appPath, reactRouterConfig.routes[match.route.id].file)
1087
1100
  ) ?? [];
1088
1101
  let styles = await getStylesForFiles({
1089
1102
  viteDevServer,
1090
1103
  rootDirectory,
1091
- cssModulesManifest,
1104
+ loadCssContents,
1092
1105
  files: [
1093
1106
  // Always include the client entry file when crawling the module graph for CSS
1094
1107
  path5.relative(rootDirectory, entryClientFilePath),
@@ -1952,33 +1965,47 @@ function toFunctionExpression(decl) {
1952
1965
  }
1953
1966
 
1954
1967
  // vite/plugin.ts
1955
- var SERVER_ONLY_ROUTE_EXPORTS = ["loader", "action", "headers"];
1956
- var CLIENT_ROUTE_EXPORTS = [
1968
+ function extractPluginContext(viteConfig) {
1969
+ return viteConfig["__reactRouterPluginContext"];
1970
+ }
1971
+ var SERVER_ONLY_ROUTE_EXPORTS = [
1972
+ "loader",
1973
+ "action",
1974
+ "unstable_middleware",
1975
+ "headers"
1976
+ ];
1977
+ var CLIENT_NON_COMPONENT_EXPORTS = [
1957
1978
  "clientAction",
1958
1979
  "clientLoader",
1959
- "default",
1960
- "ErrorBoundary",
1980
+ "unstable_clientMiddleware",
1961
1981
  "handle",
1962
- "HydrateFallback",
1963
- "Layout",
1964
- "links",
1965
1982
  "meta",
1983
+ "links",
1966
1984
  "shouldRevalidate"
1967
1985
  ];
1986
+ var CLIENT_ROUTE_EXPORTS = [
1987
+ ...CLIENT_NON_COMPONENT_EXPORTS,
1988
+ "default",
1989
+ "ErrorBoundary",
1990
+ "HydrateFallback",
1991
+ "Layout"
1992
+ ];
1968
1993
  var BUILD_CLIENT_ROUTE_QUERY_STRING = "?__react-router-build-client-route";
1969
1994
  var SSR_BUNDLE_PREFIX = "ssrBundle_";
1995
+ function isSsrBundleEnvironmentName(name) {
1996
+ return name.startsWith(SSR_BUNDLE_PREFIX);
1997
+ }
1998
+ var CSS_DEV_HELPER_ENVIRONMENT_NAME = "__react_router_css_dev_helper__";
1970
1999
  function isSeverBundleEnvironmentName(name) {
1971
2000
  return name.startsWith(SSR_BUNDLE_PREFIX);
1972
2001
  }
1973
- function getServerEnvironmentEntries(record, buildManifest) {
2002
+ function getServerEnvironmentEntries(ctx, record) {
1974
2003
  return Object.entries(record).filter(
1975
- ([name]) => buildManifest.serverBundles ? isSeverBundleEnvironmentName(name) : name === "ssr"
2004
+ ([name]) => ctx.buildManifest?.serverBundles ? isSeverBundleEnvironmentName(name) : name === "ssr"
1976
2005
  );
1977
2006
  }
1978
- function getServerEnvironmentValues(record, buildManifest) {
1979
- return getServerEnvironmentEntries(record, buildManifest).map(
1980
- ([, value]) => value
1981
- );
2007
+ function getServerEnvironmentValues(ctx, record) {
2008
+ return getServerEnvironmentEntries(ctx, record).map(([, value]) => value);
1982
2009
  }
1983
2010
  var isRouteEntryModuleId = (id) => {
1984
2011
  return id.endsWith(BUILD_CLIENT_ROUTE_QUERY_STRING);
@@ -1986,6 +2013,23 @@ var isRouteEntryModuleId = (id) => {
1986
2013
  var isRouteVirtualModule = (id) => {
1987
2014
  return isRouteEntryModuleId(id) || isRouteChunkModuleId(id);
1988
2015
  };
2016
+ var isServerBuildVirtualModuleId = (id) => {
2017
+ return id.split("?")[0] === virtual.serverBuild.id;
2018
+ };
2019
+ var getServerBuildFile = (viteManifest) => {
2020
+ let serverBuildIds = Object.keys(viteManifest).filter(
2021
+ isServerBuildVirtualModuleId
2022
+ );
2023
+ invariant(
2024
+ serverBuildIds.length <= 1,
2025
+ "Multiple server build files found in manifest"
2026
+ );
2027
+ invariant(
2028
+ serverBuildIds.length === 1,
2029
+ "Server build file not found in manifest"
2030
+ );
2031
+ return viteManifest[serverBuildIds[0]].file;
2032
+ };
1989
2033
  var virtualHmrRuntime = create("hmr-runtime");
1990
2034
  var virtualInjectHmrRuntime = create("inject-hmr-runtime");
1991
2035
  var normalizeRelativeFilePath = (file, reactRouterConfig) => {
@@ -2152,12 +2196,30 @@ var resolveEnvironmentBuildContext = ({
2152
2196
  };
2153
2197
  return resolvedBuildContext;
2154
2198
  };
2155
- var getServerBuildDirectory = (ctx, { serverBundleId } = {}) => path6.join(
2156
- ctx.reactRouterConfig.buildDirectory,
2199
+ var getServerBuildDirectory = (reactRouterConfig, { serverBundleId } = {}) => path6.join(
2200
+ reactRouterConfig.buildDirectory,
2157
2201
  "server",
2158
2202
  ...serverBundleId ? [serverBundleId] : []
2159
2203
  );
2160
2204
  var getClientBuildDirectory = (reactRouterConfig) => path6.join(reactRouterConfig.buildDirectory, "client");
2205
+ var getServerBundleRouteIds = (vitePluginContext, ctx) => {
2206
+ if (!ctx.buildManifest) {
2207
+ return void 0;
2208
+ }
2209
+ let environmentName = ctx.reactRouterConfig.future.unstable_viteEnvironmentApi ? vitePluginContext.environment.name : ctx.environmentBuildContext?.name;
2210
+ if (!environmentName || !isSsrBundleEnvironmentName(environmentName)) {
2211
+ return void 0;
2212
+ }
2213
+ let serverBundleId = environmentName.replace(SSR_BUNDLE_PREFIX, "");
2214
+ let routesByServerBundleId = getRoutesByServerBundleId(ctx.buildManifest);
2215
+ let serverBundleRoutes = routesByServerBundleId[serverBundleId];
2216
+ invariant(
2217
+ serverBundleRoutes,
2218
+ `Routes not found for server bundle "${serverBundleId}"`
2219
+ );
2220
+ return Object.keys(serverBundleRoutes);
2221
+ };
2222
+ var injectQuery = (url2, query) => url2.includes("?") ? url2.replace("?", `?${query}&`) : `${url2}?${query}`;
2161
2223
  var defaultEntriesDir = path6.resolve(
2162
2224
  path6.dirname(require.resolve("@react-router/dev/package.json")),
2163
2225
  "dist",
@@ -2166,14 +2228,13 @@ var defaultEntriesDir = path6.resolve(
2166
2228
  );
2167
2229
  var defaultEntries = fse.readdirSync(defaultEntriesDir).map((filename3) => path6.join(defaultEntriesDir, filename3));
2168
2230
  invariant(defaultEntries.length > 0, "No default entries found");
2169
- var reactRouterDevLoadContext = () => ({});
2231
+ var reactRouterDevLoadContext = () => void 0;
2170
2232
  var reactRouterVitePlugin = () => {
2171
2233
  let rootDirectory;
2172
2234
  let viteCommand;
2173
2235
  let viteUserConfig;
2174
2236
  let viteConfigEnv;
2175
2237
  let viteConfig;
2176
- let buildManifest;
2177
2238
  let cssModulesManifest = {};
2178
2239
  let viteChildCompiler = null;
2179
2240
  let cache = /* @__PURE__ */ new Map();
@@ -2194,6 +2255,7 @@ var reactRouterVitePlugin = () => {
2194
2255
  }
2195
2256
  return;
2196
2257
  }
2258
+ let injectedPluginContext = !reactRouterConfig.future.unstable_viteEnvironmentApi && viteCommand === "build" ? extractPluginContext(viteUserConfig) : void 0;
2197
2259
  let { entryClientFilePath, entryServerFilePath } = await resolveEntryFiles({
2198
2260
  rootDirectory,
2199
2261
  reactRouterConfig
@@ -2208,6 +2270,7 @@ var reactRouterVitePlugin = () => {
2208
2270
  process.exit(1);
2209
2271
  }
2210
2272
  let viteManifestEnabled = viteUserConfig.build?.manifest === true;
2273
+ let buildManifest = viteCommand === "build" ? injectedPluginContext?.buildManifest ?? await getBuildManifest({ reactRouterConfig, rootDirectory }) : null;
2211
2274
  let environmentBuildContext = viteCommand === "build" ? resolveEnvironmentBuildContext({ viteCommand, viteUserConfig }) : null;
2212
2275
  firstLoad = false;
2213
2276
  ctx = {
@@ -2217,7 +2280,8 @@ var reactRouterVitePlugin = () => {
2217
2280
  entryClientFilePath,
2218
2281
  entryServerFilePath,
2219
2282
  publicPath,
2220
- viteManifestEnabled
2283
+ viteManifestEnabled,
2284
+ buildManifest
2221
2285
  };
2222
2286
  };
2223
2287
  let pluginIndex = (pluginName) => {
@@ -2239,21 +2303,26 @@ var reactRouterVitePlugin = () => {
2239
2303
  ctx.reactRouterConfig.ssr,
2240
2304
  routes
2241
2305
  );
2306
+ let isSpaMode = isSpaModeEnabled(ctx.reactRouterConfig);
2242
2307
  return `
2243
2308
  import * as entryServer from ${JSON.stringify(
2244
2309
  resolveFileUrl(ctx, ctx.entryServerFilePath)
2245
2310
  )};
2246
2311
  ${Object.keys(routes).map((key, index) => {
2247
2312
  let route = routes[key];
2248
- return `import * as route${index} from ${JSON.stringify(
2249
- resolveFileUrl(
2250
- ctx,
2251
- resolveRelativeRouteFilePath(route, ctx.reactRouterConfig)
2252
- )
2253
- )};`;
2313
+ if (isSpaMode && key !== "root") {
2314
+ return `const route${index} = { default: () => null };`;
2315
+ } else {
2316
+ return `import * as route${index} from ${JSON.stringify(
2317
+ resolveFileUrl(
2318
+ ctx,
2319
+ resolveRelativeRouteFilePath(route, ctx.reactRouterConfig)
2320
+ )
2321
+ )};`;
2322
+ }
2254
2323
  }).join("\n")}
2255
2324
  export { default as assets } from ${JSON.stringify(
2256
- `${virtual.serverManifest.id}${routeIds ? `?route-ids=${routeIds.join(",")}` : ""}`
2325
+ virtual.serverManifest.id
2257
2326
  )};
2258
2327
  export const assetsBuildDirectory = ${JSON.stringify(
2259
2328
  path6.relative(
@@ -2264,7 +2333,7 @@ var reactRouterVitePlugin = () => {
2264
2333
  export const basename = ${JSON.stringify(ctx.reactRouterConfig.basename)};
2265
2334
  export const future = ${JSON.stringify(ctx.reactRouterConfig.future)};
2266
2335
  export const ssr = ${ctx.reactRouterConfig.ssr};
2267
- export const isSpaMode = ${isSpaModeEnabled(ctx.reactRouterConfig)};
2336
+ export const isSpaMode = ${isSpaMode};
2268
2337
  export const prerender = ${JSON.stringify(prerenderPaths)};
2269
2338
  export const publicPath = ${JSON.stringify(ctx.publicPath)};
2270
2339
  export const entry = { module: entryServer };
@@ -2280,7 +2349,15 @@ var reactRouterVitePlugin = () => {
2280
2349
  module: route${index}
2281
2350
  }`;
2282
2351
  }).join(",\n ")}
2283
- };`;
2352
+ };
2353
+ ${ctx.reactRouterConfig.future.unstable_viteEnvironmentApi && viteCommand === "serve" ? `
2354
+ export const getCriticalCss = ({ pathname }) => {
2355
+ return {
2356
+ rel: "stylesheet",
2357
+ href: "${viteUserConfig.base ?? "/"}@react-router/critical.css?pathname=" + pathname,
2358
+ };
2359
+ }
2360
+ ` : ""}`;
2284
2361
  };
2285
2362
  let loadViteManifest = async (directory) => {
2286
2363
  let manifestContents = await fse.readFile(
@@ -2414,6 +2491,7 @@ var reactRouterVitePlugin = () => {
2414
2491
  reactRouterServerManifest
2415
2492
  };
2416
2493
  };
2494
+ let currentReactRouterManifestForDev = null;
2417
2495
  let getReactRouterManifestForDev = async () => {
2418
2496
  let routes = {};
2419
2497
  let routeManifestExports = await getRouteManifestModuleExports(
@@ -2470,7 +2548,7 @@ var reactRouterVitePlugin = () => {
2470
2548
  imports: []
2471
2549
  };
2472
2550
  }
2473
- return {
2551
+ let reactRouterManifestForDev = {
2474
2552
  version: String(Math.random()),
2475
2553
  url: combineURLs(ctx.publicPath, virtual.browserManifest.url),
2476
2554
  hmr: {
@@ -2485,6 +2563,42 @@ var reactRouterVitePlugin = () => {
2485
2563
  },
2486
2564
  routes
2487
2565
  };
2566
+ currentReactRouterManifestForDev = reactRouterManifestForDev;
2567
+ return reactRouterManifestForDev;
2568
+ };
2569
+ const loadCssContents = async (viteDevServer, dep) => {
2570
+ invariant(
2571
+ viteCommand === "serve",
2572
+ "loadCssContents is only available in dev mode"
2573
+ );
2574
+ if (dep.file && isCssModulesFile(dep.file)) {
2575
+ return cssModulesManifest[dep.file];
2576
+ }
2577
+ const vite2 = getVite();
2578
+ const viteMajor = parseInt(vite2.version.split(".")[0], 10);
2579
+ const url2 = viteMajor >= 6 ? (
2580
+ // We need the ?inline query in Vite v6 when loading CSS in SSR
2581
+ // since it does not expose the default export for CSS in a
2582
+ // server environment. This is to align with non-SSR
2583
+ // environments. For backwards compatibility with v5 we keep
2584
+ // using the URL without ?inline query because the HMR code was
2585
+ // relying on the implicit SSR-client module graph relationship.
2586
+ injectQuery(dep.url, "inline")
2587
+ ) : dep.url;
2588
+ let cssMod;
2589
+ if (ctx.reactRouterConfig.future.unstable_viteEnvironmentApi) {
2590
+ const cssDevHelperEnvironment = viteDevServer.environments[CSS_DEV_HELPER_ENVIRONMENT_NAME];
2591
+ invariant(cssDevHelperEnvironment, "Missing CSS dev helper environment");
2592
+ invariant(vite2.isRunnableDevEnvironment(cssDevHelperEnvironment));
2593
+ cssMod = await cssDevHelperEnvironment.runner.import(url2);
2594
+ } else {
2595
+ cssMod = await viteDevServer.ssrLoadModule(url2);
2596
+ }
2597
+ invariant(
2598
+ typeof cssMod === "object" && cssMod !== null && "default" in cssMod && typeof cssMod.default === "string",
2599
+ `Failed to load CSS for ${dep.file ?? dep.url}`
2600
+ );
2601
+ return cssMod.default;
2488
2602
  };
2489
2603
  return [
2490
2604
  {
@@ -2513,7 +2627,6 @@ var reactRouterVitePlugin = () => {
2513
2627
  watch: viteCommand === "serve"
2514
2628
  });
2515
2629
  await updatePluginContext();
2516
- buildManifest = await getBuildManifest(ctx);
2517
2630
  Object.assign(
2518
2631
  process.env,
2519
2632
  vite2.loadEnv(
@@ -2525,15 +2638,12 @@ var reactRouterVitePlugin = () => {
2525
2638
  ""
2526
2639
  )
2527
2640
  );
2528
- let environments = await getEnvironmentsOptions(
2529
- ctx,
2530
- buildManifest,
2531
- viteCommand,
2532
- { viteUserConfig }
2533
- );
2641
+ let environments = await getEnvironmentsOptions(ctx, viteCommand, {
2642
+ viteUserConfig
2643
+ });
2534
2644
  let serverEnvironment = getServerEnvironmentValues(
2535
- environments,
2536
- buildManifest
2645
+ ctx,
2646
+ environments
2537
2647
  )[0];
2538
2648
  invariant(serverEnvironment);
2539
2649
  let clientEnvironment = environments.client;
@@ -2604,7 +2714,6 @@ var reactRouterVitePlugin = () => {
2604
2714
  sharedPlugins: true,
2605
2715
  async buildApp(builder) {
2606
2716
  invariant(viteConfig);
2607
- invariant(buildManifest);
2608
2717
  viteConfig.logger.info(
2609
2718
  "Using Vite Environment API (experimental)"
2610
2719
  );
@@ -2612,11 +2721,13 @@ var reactRouterVitePlugin = () => {
2612
2721
  await cleanBuildDirectory(viteConfig, ctx);
2613
2722
  await builder.build(builder.environments.client);
2614
2723
  let serverEnvironments = getServerEnvironmentValues(
2615
- builder.environments,
2616
- buildManifest
2724
+ ctx,
2725
+ builder.environments
2617
2726
  );
2618
2727
  await Promise.all(serverEnvironments.map(builder.build));
2619
2728
  await cleanViteManifests(environments, ctx);
2729
+ let { buildManifest } = ctx;
2730
+ invariant(buildManifest, "Expected build manifest");
2620
2731
  await reactRouterConfig.buildEnd?.({
2621
2732
  buildManifest,
2622
2733
  reactRouterConfig,
@@ -2663,6 +2774,8 @@ var reactRouterVitePlugin = () => {
2663
2774
  }
2664
2775
  viteChildCompiler = await vite2.createServer({
2665
2776
  ...viteUserConfig,
2777
+ // Ensure child compiler cannot overwrite the default cache directory
2778
+ cacheDir: "node_modules/.vite-child-compiler",
2666
2779
  mode: viteConfig.mode,
2667
2780
  server: {
2668
2781
  watch: viteConfig.command === "build" ? null : void 0,
@@ -2674,7 +2787,23 @@ var reactRouterVitePlugin = () => {
2674
2787
  plugins: [
2675
2788
  ...(childCompilerConfigFile.config.plugins ?? []).flat().filter(
2676
2789
  (plugin2) => typeof plugin2 === "object" && plugin2 !== null && "name" in plugin2 && plugin2.name !== "react-router" && plugin2.name !== "react-router:route-exports" && plugin2.name !== "react-router:hmr-updates"
2677
- )
2790
+ ),
2791
+ {
2792
+ name: "react-router:override-optimize-deps",
2793
+ config(userConfig) {
2794
+ if (ctx.reactRouterConfig.future.unstable_viteEnvironmentApi && userConfig.environments) {
2795
+ for (const environmentName of Object.keys(
2796
+ userConfig.environments
2797
+ )) {
2798
+ userConfig.environments[environmentName].optimizeDeps = {
2799
+ noDiscovery: true
2800
+ };
2801
+ }
2802
+ } else {
2803
+ userConfig.optimizeDeps = { noDiscovery: true };
2804
+ }
2805
+ }
2806
+ }
2678
2807
  ]
2679
2808
  });
2680
2809
  await viteChildCompiler.pluginContainer.buildStart({});
@@ -2705,15 +2834,14 @@ var reactRouterVitePlugin = () => {
2705
2834
  (0, import_react_router2.unstable_setDevServerHooks)({
2706
2835
  // Give the request handler access to the critical CSS in dev to avoid a
2707
2836
  // flash of unstyled content since Vite injects CSS file contents via JS
2708
- getCriticalCss: async (build, url2) => {
2709
- return getStylesForUrl({
2837
+ getCriticalCss: async (pathname) => {
2838
+ return getStylesForPathname({
2710
2839
  rootDirectory: ctx.rootDirectory,
2711
2840
  entryClientFilePath: ctx.entryClientFilePath,
2712
2841
  reactRouterConfig: ctx.reactRouterConfig,
2713
2842
  viteDevServer,
2714
- cssModulesManifest,
2715
- build,
2716
- url: url2
2843
+ loadCssContents,
2844
+ pathname
2717
2845
  });
2718
2846
  },
2719
2847
  // If an error is caught within the request handler, let Vite fix the
@@ -2756,13 +2884,48 @@ var reactRouterVitePlugin = () => {
2756
2884
  }
2757
2885
  }
2758
2886
  );
2887
+ if (ctx.reactRouterConfig.future.unstable_viteEnvironmentApi) {
2888
+ viteDevServer.middlewares.use(async (req, res, next) => {
2889
+ let [reqPathname, reqSearch] = (req.url ?? "").split("?");
2890
+ if (reqPathname === "/@react-router/critical.css") {
2891
+ let pathname = new URLSearchParams(reqSearch).get("pathname");
2892
+ if (!pathname) {
2893
+ return next("No pathname provided");
2894
+ }
2895
+ let css = await getStylesForPathname({
2896
+ rootDirectory: ctx.rootDirectory,
2897
+ entryClientFilePath: ctx.entryClientFilePath,
2898
+ reactRouterConfig: ctx.reactRouterConfig,
2899
+ viteDevServer,
2900
+ loadCssContents,
2901
+ pathname
2902
+ });
2903
+ res.setHeader("Content-Type", "text/css");
2904
+ res.end(css);
2905
+ } else {
2906
+ next();
2907
+ }
2908
+ });
2909
+ }
2759
2910
  return () => {
2760
2911
  if (!viteDevServer.config.server.middlewareMode) {
2761
2912
  viteDevServer.middlewares.use(async (req, res, next) => {
2762
2913
  try {
2763
- let build = await viteDevServer.ssrLoadModule(
2764
- virtual.serverBuild.id
2765
- );
2914
+ let build;
2915
+ if (ctx.reactRouterConfig.future.unstable_viteEnvironmentApi) {
2916
+ let vite2 = getVite();
2917
+ let ssrEnvironment = viteDevServer.environments.ssr;
2918
+ if (!vite2.isRunnableDevEnvironment(ssrEnvironment)) {
2919
+ return;
2920
+ }
2921
+ build = await ssrEnvironment.runner.import(
2922
+ virtual.serverBuild.id
2923
+ );
2924
+ } else {
2925
+ build = await viteDevServer.ssrLoadModule(
2926
+ virtual.serverBuild.id
2927
+ );
2928
+ }
2766
2929
  let handler = (0, import_react_router2.createRequestHandler)(build, "development");
2767
2930
  let nodeHandler = async (nodeReq, nodeRes) => {
2768
2931
  let req2 = fromNodeRequest(nodeReq, nodeRes);
@@ -2792,7 +2955,7 @@ var reactRouterVitePlugin = () => {
2792
2955
  let clientBuildDirectory = getClientBuildDirectory(
2793
2956
  ctx.reactRouterConfig
2794
2957
  );
2795
- let serverBuildDirectory = future.unstable_viteEnvironmentApi ? this.environment.config?.build?.outDir : ctx.environmentBuildContext?.options.build?.outDir ?? getServerBuildDirectory(ctx);
2958
+ let serverBuildDirectory = future.unstable_viteEnvironmentApi ? this.environment.config?.build?.outDir : ctx.environmentBuildContext?.options.build?.outDir ?? getServerBuildDirectory(ctx.reactRouterConfig);
2796
2959
  let ssrViteManifest = await loadViteManifest(serverBuildDirectory);
2797
2960
  let ssrAssetPaths = getViteManifestAssetPaths(ssrViteManifest);
2798
2961
  let movedAssetPaths = [];
@@ -2831,7 +2994,7 @@ var reactRouterVitePlugin = () => {
2831
2994
  viteConfig,
2832
2995
  ctx.reactRouterConfig,
2833
2996
  serverBuildDirectory,
2834
- ssrViteManifest[virtual.serverBuild.id].file,
2997
+ getServerBuildFile(ssrViteManifest),
2835
2998
  clientBuildDirectory
2836
2999
  );
2837
3000
  }
@@ -2840,7 +3003,7 @@ var reactRouterVitePlugin = () => {
2840
3003
  viteConfig,
2841
3004
  ctx.reactRouterConfig,
2842
3005
  serverBuildDirectory,
2843
- ssrViteManifest[virtual.serverBuild.id].file,
3006
+ getServerBuildFile(ssrViteManifest),
2844
3007
  clientBuildDirectory
2845
3008
  );
2846
3009
  }
@@ -2981,22 +3144,17 @@ var reactRouterVitePlugin = () => {
2981
3144
  name: "react-router:virtual-modules",
2982
3145
  enforce: "pre",
2983
3146
  resolveId(id) {
2984
- let [baseId, queryString] = id.split("?");
2985
- const vmod2 = Object.values(virtual).find((vmod3) => vmod3.id === baseId);
2986
- if (vmod2)
2987
- return vmod2.resolvedId + (queryString ? `?${queryString}` : "");
3147
+ const vmod2 = Object.values(virtual).find((vmod3) => vmod3.id === id);
3148
+ if (vmod2) return vmod2.resolvedId;
2988
3149
  },
2989
3150
  async load(id) {
2990
- let [baseId, queryString] = id.split("?");
2991
- switch (baseId) {
3151
+ switch (id) {
2992
3152
  case virtual.serverBuild.resolvedId: {
2993
- let searchParams = new URLSearchParams(queryString);
2994
- let routeIds = searchParams.get("route-ids")?.split(",") || void 0;
3153
+ let routeIds = getServerBundleRouteIds(this, ctx);
2995
3154
  return await getServerEntry({ routeIds });
2996
3155
  }
2997
3156
  case virtual.serverManifest.resolvedId: {
2998
- let searchParams = new URLSearchParams(queryString);
2999
- let routeIds = searchParams.get("route-ids")?.split(",") || void 0;
3157
+ let routeIds = getServerBundleRouteIds(this, ctx);
3000
3158
  let reactRouterManifest = viteCommand === "build" ? (await generateReactRouterManifestsForBuild({
3001
3159
  routeIds
3002
3160
  })).reactRouterServerManifest : await getReactRouterManifestForDev();
@@ -3231,8 +3389,7 @@ var reactRouterVitePlugin = () => {
3231
3389
  let route = getRoute(ctx.reactRouterConfig, file);
3232
3390
  let hmrEventData = { route: null };
3233
3391
  if (route) {
3234
- let serverManifest = (await server.ssrLoadModule(virtual.serverManifest.id)).default;
3235
- let oldRouteMetadata = serverManifest.routes[route.id];
3392
+ let oldRouteMetadata = currentReactRouterManifestForDev?.routes[route.id];
3236
3393
  let newRouteMetadata = await getRouteMetadata(
3237
3394
  cache,
3238
3395
  ctx,
@@ -3312,14 +3469,7 @@ function uniqueNodes(nodes) {
3312
3469
  }
3313
3470
  function addRefreshWrapper(reactRouterConfig, code, id) {
3314
3471
  let route = getRoute(reactRouterConfig, id);
3315
- let acceptExports = route ? [
3316
- "clientAction",
3317
- "clientLoader",
3318
- "handle",
3319
- "meta",
3320
- "links",
3321
- "shouldRevalidate"
3322
- ] : [];
3472
+ let acceptExports = route ? CLIENT_NON_COMPONENT_EXPORTS : [];
3323
3473
  return REACT_REFRESH_HEADER.replaceAll("__SOURCE__", JSON.stringify(id)) + code + REACT_REFRESH_FOOTER.replaceAll("__SOURCE__", JSON.stringify(id)).replaceAll("__ACCEPT_EXPORTS__", JSON.stringify(acceptExports)).replaceAll("__ROUTE_ID__", JSON.stringify(route?.id));
3324
3474
  }
3325
3475
  var REACT_REFRESH_HEADER = `
@@ -3484,18 +3634,26 @@ async function handlePrerender(viteConfig, reactRouterConfig, serverBuildDirecto
3484
3634
  serverBuildDirectory,
3485
3635
  serverBuildPath
3486
3636
  );
3487
- let routes = createPrerenderRoutes(build.routes);
3637
+ let routes = createPrerenderRoutes(reactRouterConfig.routes);
3638
+ for (let path7 of build.prerender) {
3639
+ let matches = (0, import_react_router2.matchRoutes)(routes, `/${path7}/`.replace(/^\/\/+/, "/"));
3640
+ if (!matches) {
3641
+ throw new Error(
3642
+ `Unable to prerender path because it does not match any routes: ${path7}`
3643
+ );
3644
+ }
3645
+ }
3646
+ let buildRoutes = createPrerenderRoutes(build.routes);
3488
3647
  let headers = {
3489
3648
  // Header that can be used in the loader to know if you're running at
3490
3649
  // build time or runtime
3491
3650
  "X-React-Router-Prerender": "yes"
3492
3651
  };
3493
3652
  for (let path7 of build.prerender) {
3494
- let matches = (0, import_react_router2.matchRoutes)(routes, `/${path7}/`.replace(/^\/\/+/, "/"));
3495
- invariant(
3496
- matches,
3497
- `Unable to prerender path because it does not match any routes: ${path7}`
3498
- );
3653
+ let matches = (0, import_react_router2.matchRoutes)(buildRoutes, `/${path7}/`.replace(/^\/\/+/, "/"));
3654
+ if (!matches) {
3655
+ continue;
3656
+ }
3499
3657
  let leafRoute = matches ? matches[matches.length - 1].route : null;
3500
3658
  let manifestRoute = leafRoute ? build.routes[leafRoute.id]?.module : null;
3501
3659
  let isResourceRoute = manifestRoute && !manifestRoute.default && !manifestRoute.ErrorBoundary;
@@ -3798,8 +3956,8 @@ function getRouteBranch(routes, routeId) {
3798
3956
  }
3799
3957
  return branch.reverse();
3800
3958
  }
3801
- function hasServerBundles(buildManifest) {
3802
- return Object.keys(buildManifest.serverBundles ?? {}).length > 0;
3959
+ function getServerBundleIds(ctx) {
3960
+ return ctx.buildManifest?.serverBundles ? Object.keys(ctx.buildManifest.serverBundles) : void 0;
3803
3961
  }
3804
3962
  function getRoutesByServerBundleId(buildManifest) {
3805
3963
  if (!buildManifest.routeIdToServerBundleId) {
@@ -3914,19 +4072,22 @@ async function cleanViteManifests(environmentsOptions, ctx) {
3914
4072
  })
3915
4073
  );
3916
4074
  }
3917
- async function getBuildManifest(ctx) {
3918
- let { routes, serverBundles, appDirectory } = ctx.reactRouterConfig;
4075
+ async function getBuildManifest({
4076
+ reactRouterConfig,
4077
+ rootDirectory
4078
+ }) {
4079
+ let { routes, serverBundles, appDirectory } = reactRouterConfig;
3919
4080
  if (!serverBundles) {
3920
4081
  return { routes };
3921
4082
  }
3922
4083
  let { normalizePath } = await import("vite");
3923
- let serverBuildDirectory = getServerBuildDirectory(ctx);
3924
- let resolvedAppDirectory = path6.resolve(ctx.rootDirectory, appDirectory);
4084
+ let serverBuildDirectory = getServerBuildDirectory(reactRouterConfig);
4085
+ let resolvedAppDirectory = path6.resolve(rootDirectory, appDirectory);
3925
4086
  let rootRelativeRoutes = Object.fromEntries(
3926
4087
  Object.entries(routes).map(([id, route]) => {
3927
4088
  let filePath = path6.join(resolvedAppDirectory, route.file);
3928
4089
  let rootRelativeFilePath = normalizePath(
3929
- path6.relative(ctx.rootDirectory, filePath)
4090
+ path6.relative(rootDirectory, filePath)
3930
4091
  );
3931
4092
  return [id, { ...route, file: rootRelativeFilePath }];
3932
4093
  })
@@ -3951,10 +4112,18 @@ async function getBuildManifest(ctx) {
3951
4112
  if (typeof serverBundleId !== "string") {
3952
4113
  throw new Error(`The "serverBundles" function must return a string`);
3953
4114
  }
3954
- if (!/^[a-zA-Z0-9-_]+$/.test(serverBundleId)) {
3955
- throw new Error(
3956
- `The "serverBundles" function must only return strings containing alphanumeric characters, hyphens and underscores.`
3957
- );
4115
+ if (reactRouterConfig.future.unstable_viteEnvironmentApi) {
4116
+ if (!/^[a-zA-Z0-9_]+$/.test(serverBundleId)) {
4117
+ throw new Error(
4118
+ `The "serverBundles" function must only return strings containing alphanumeric characters and underscores.`
4119
+ );
4120
+ }
4121
+ } else {
4122
+ if (!/^[a-zA-Z0-9-_]+$/.test(serverBundleId)) {
4123
+ throw new Error(
4124
+ `The "serverBundles" function must only return strings containing alphanumeric characters, hyphens and underscores.`
4125
+ );
4126
+ }
3958
4127
  }
3959
4128
  buildManifest.routeIdToServerBundleId[route.id] = serverBundleId;
3960
4129
  buildManifest.serverBundles[serverBundleId] ??= {
@@ -3962,10 +4131,10 @@ async function getBuildManifest(ctx) {
3962
4131
  file: normalizePath(
3963
4132
  path6.join(
3964
4133
  path6.relative(
3965
- ctx.rootDirectory,
4134
+ rootDirectory,
3966
4135
  path6.join(serverBuildDirectory, serverBundleId)
3967
4136
  ),
3968
- ctx.reactRouterConfig.serverBuildFile
4137
+ reactRouterConfig.serverBuildFile
3969
4138
  )
3970
4139
  )
3971
4140
  };
@@ -3980,7 +4149,7 @@ function mergeEnvironmentOptions(base, ...overrides) {
3980
4149
  base
3981
4150
  );
3982
4151
  }
3983
- async function getEnvironmentOptionsResolvers(ctx, buildManifest, viteCommand) {
4152
+ async function getEnvironmentOptionsResolvers(ctx, viteCommand) {
3984
4153
  let { serverBuildFile, serverModuleFormat } = ctx.reactRouterConfig;
3985
4154
  let packageRoot = path6.dirname(
3986
4155
  require.resolve("@react-router/dev/package.json")
@@ -4024,7 +4193,15 @@ async function getEnvironmentOptionsResolvers(ctx, buildManifest, viteCommand) {
4024
4193
  let conditions = viteCommand === "build" ? viteServerConditions : ["development", ...viteServerConditions];
4025
4194
  return mergeEnvironmentOptions(getBaseOptions({ viteUserConfig }), {
4026
4195
  resolve: {
4027
- external: ssrExternals,
4196
+ external: (
4197
+ // This check is required to honor the "noExternal: true" config
4198
+ // provided by vite-plugin-cloudflare within this repo. When compiling
4199
+ // for Cloudflare, all server dependencies are externalized, but our
4200
+ // `ssrExternals` config inadvertently overrides this. This doesn't
4201
+ // impact consumers because for them `ssrExternals` is undefined and
4202
+ // Cloudflare's "noExternal: true" config remains intact.
4203
+ ctx.reactRouterConfig.future.unstable_viteEnvironmentApi && viteUserConfig.environments?.ssr?.resolve?.noExternal === true ? void 0 : ssrExternals
4204
+ ),
4028
4205
  conditions,
4029
4206
  externalConditions: conditions
4030
4207
  },
@@ -4038,6 +4215,7 @@ async function getEnvironmentOptionsResolvers(ctx, buildManifest, viteCommand) {
4038
4215
  copyPublicDir: false,
4039
4216
  // Assets in the public directory are only used by the client
4040
4217
  rollupOptions: {
4218
+ input: (ctx.reactRouterConfig.future.unstable_viteEnvironmentApi ? viteUserConfig.environments?.ssr?.build?.rollupOptions?.input : viteUserConfig.build?.rollupOptions?.input) ?? virtual.serverBuild.id,
4041
4219
  output: {
4042
4220
  entryFileNames: serverBuildFile,
4043
4221
  format: serverModuleFormat
@@ -4069,12 +4247,15 @@ async function getEnvironmentOptionsResolvers(ctx, buildManifest, viteCommand) {
4069
4247
  }
4070
4248
  )
4071
4249
  ],
4072
- output: {
4073
- entryFileNames({ moduleIds }) {
4250
+ output: (ctx.reactRouterConfig.future.unstable_viteEnvironmentApi ? viteUserConfig?.environments?.client?.build?.rollupOptions?.output : viteUserConfig?.build?.rollupOptions?.output) ?? {
4251
+ entryFileNames: ({ moduleIds }) => {
4074
4252
  let routeChunkModuleId = moduleIds.find(isRouteChunkModuleId);
4075
4253
  let routeChunkName = routeChunkModuleId ? getRouteChunkNameFromModuleId(routeChunkModuleId) : null;
4076
4254
  let routeChunkSuffix = routeChunkName ? `-${(0, import_kebabCase.default)(routeChunkName)}` : "";
4077
- return `assets/[name]${routeChunkSuffix}-[hash].js`;
4255
+ return path6.posix.join(
4256
+ (ctx.reactRouterConfig.future.unstable_viteEnvironmentApi ? viteUserConfig?.environments?.client?.build?.assetsDir : viteUserConfig?.build?.assetsDir) ?? "assets",
4257
+ `[name]${routeChunkSuffix}-[hash].js`
4258
+ );
4078
4259
  }
4079
4260
  }
4080
4261
  },
@@ -4082,22 +4263,17 @@ async function getEnvironmentOptionsResolvers(ctx, buildManifest, viteCommand) {
4082
4263
  }
4083
4264
  })
4084
4265
  };
4085
- if (hasServerBundles(buildManifest)) {
4086
- for (let [serverBundleId, routes] of Object.entries(
4087
- getRoutesByServerBundleId(buildManifest)
4088
- )) {
4089
- const serverBundleEnvironmentId = serverBundleId.replaceAll("-", "_");
4090
- const environmentName = `${SSR_BUNDLE_PREFIX}${serverBundleEnvironmentId}`;
4266
+ let serverBundleIds = getServerBundleIds(ctx);
4267
+ if (serverBundleIds) {
4268
+ for (let serverBundleId of serverBundleIds) {
4269
+ const environmentName = `${SSR_BUNDLE_PREFIX}${serverBundleId}`;
4091
4270
  environmentOptionsResolvers[environmentName] = ({ viteUserConfig }) => mergeEnvironmentOptions(
4092
4271
  getBaseServerOptions({ viteUserConfig }),
4093
4272
  {
4094
4273
  build: {
4095
- outDir: getServerBuildDirectory(ctx, { serverBundleId }),
4096
- rollupOptions: {
4097
- input: `${virtual.serverBuild.id}?route-ids=${Object.keys(
4098
- routes
4099
- ).join(",")}`
4100
- }
4274
+ outDir: getServerBuildDirectory(ctx.reactRouterConfig, {
4275
+ serverBundleId
4276
+ })
4101
4277
  }
4102
4278
  },
4103
4279
  // Ensure server bundle environments extend the user's SSR
@@ -4108,13 +4284,27 @@ async function getEnvironmentOptionsResolvers(ctx, buildManifest, viteCommand) {
4108
4284
  } else {
4109
4285
  environmentOptionsResolvers.ssr = ({ viteUserConfig }) => mergeEnvironmentOptions(getBaseServerOptions({ viteUserConfig }), {
4110
4286
  build: {
4111
- outDir: getServerBuildDirectory(ctx),
4112
- rollupOptions: {
4113
- input: (ctx.reactRouterConfig.future.unstable_viteEnvironmentApi ? viteUserConfig.environments?.ssr?.build?.rollupOptions?.input : viteUserConfig.build?.rollupOptions?.input) ?? virtual.serverBuild.id
4114
- }
4115
- }
4287
+ outDir: getServerBuildDirectory(ctx.reactRouterConfig)
4288
+ },
4289
+ optimizeDeps: ctx.reactRouterConfig.future.unstable_viteEnvironmentApi && viteUserConfig.environments?.ssr?.optimizeDeps?.noDiscovery === false ? {
4290
+ entries: [
4291
+ vite2.normalizePath(ctx.entryServerFilePath),
4292
+ ...Object.values(ctx.reactRouterConfig.routes).map(
4293
+ (route) => resolveRelativeRouteFilePath(route, ctx.reactRouterConfig)
4294
+ )
4295
+ ],
4296
+ include: [
4297
+ "react",
4298
+ "react/jsx-dev-runtime",
4299
+ "react-dom/server",
4300
+ "react-router"
4301
+ ]
4302
+ } : void 0
4116
4303
  });
4117
4304
  }
4305
+ if (ctx.reactRouterConfig.future.unstable_viteEnvironmentApi && viteCommand === "serve") {
4306
+ environmentOptionsResolvers[CSS_DEV_HELPER_ENVIRONMENT_NAME] = () => ({});
4307
+ }
4118
4308
  return environmentOptionsResolvers;
4119
4309
  }
4120
4310
  function resolveEnvironmentsOptions(environmentResolvers, resolverOptions) {
@@ -4126,10 +4316,9 @@ function resolveEnvironmentsOptions(environmentResolvers, resolverOptions) {
4126
4316
  }
4127
4317
  return environmentOptions;
4128
4318
  }
4129
- async function getEnvironmentsOptions(ctx, buildManifest, viteCommand, resolverOptions) {
4319
+ async function getEnvironmentsOptions(ctx, viteCommand, resolverOptions) {
4130
4320
  let environmentOptionsResolvers = await getEnvironmentOptionsResolvers(
4131
4321
  ctx,
4132
- buildManifest,
4133
4322
  viteCommand
4134
4323
  );
4135
4324
  return resolveEnvironmentsOptions(