@react-router/dev 0.0.0-experimental-1b454267f → 0.0.0-experimental-d499f664f

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/cli/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * @react-router/dev v0.0.0-experimental-1b454267f
3
+ * @react-router/dev v0.0.0-experimental-d499f664f
4
4
  *
5
5
  * Copyright (c) Remix Software Inc.
6
6
  *
@@ -389,6 +389,7 @@ async function resolveConfig({
389
389
  );
390
390
  }
391
391
  let future = {
392
+ unstable_middleware: reactRouterUserConfig.future?.unstable_middleware ?? false,
392
393
  unstable_optimizeDeps: reactRouterUserConfig.future?.unstable_optimizeDeps ?? false,
393
394
  unstable_splitRouteModules: reactRouterUserConfig.future?.unstable_splitRouteModules ?? false,
394
395
  unstable_viteEnvironmentApi: reactRouterUserConfig.future?.unstable_viteEnvironmentApi ?? false
@@ -516,7 +517,7 @@ function findEntry(dir, basename2, options) {
516
517
  }
517
518
  return void 0;
518
519
  }
519
- var import_node_fs, import_node_child_process, import_package_json, import_pathe3, import_chokidar, import_picocolors, import_pick2, import_omit, import_cloneDeep, import_isEqual, excludedConfigPresetKeys, branchRouteProperties, configRouteToBranchRoute, mergeReactRouterConfig, deepFreeze, ssrExternals, entryExts;
520
+ var import_node_fs, import_node_child_process, import_package_json, import_pathe3, import_chokidar, import_picocolors, import_pick2, import_omit, import_cloneDeep, import_isEqual, excludedConfigPresetKeys, mergeReactRouterConfig, deepFreeze, ssrExternals, entryExts;
520
521
  var init_config = __esm({
521
522
  "config/config.ts"() {
522
523
  "use strict";
@@ -535,13 +536,6 @@ var init_config = __esm({
535
536
  init_detectPackageManager();
536
537
  init_is_react_router_repo();
537
538
  excludedConfigPresetKeys = ["presets"];
538
- branchRouteProperties = [
539
- "id",
540
- "path",
541
- "file",
542
- "index"
543
- ];
544
- configRouteToBranchRoute = (configRoute) => (0, import_pick2.default)(configRoute, branchRouteProperties);
545
539
  mergeReactRouterConfig = (...configs) => {
546
540
  let reducer = (configA, configB) => {
547
541
  let mergeRequired = (key) => configA[key] !== void 0 && configB[key] !== void 0;
@@ -769,6 +763,8 @@ function generate2(ctx, route) {
769
763
  export type HeadersArgs = T.HeadersArgs
770
764
  export type HeadersFunction = (args: HeadersArgs) => Headers | HeadersInit
771
765
 
766
+ export type unstable_MiddlewareFunction = T.CreateServerMiddlewareFunction<Info>
767
+ export type unstable_ClientMiddlewareFunction = T.CreateClientMiddlewareFunction<Info>
772
768
  export type LoaderArgs = T.CreateServerLoaderArgs<Info>
773
769
  export type ClientLoaderArgs = T.CreateClientLoaderArgs<Info>
774
770
  export type ActionArgs = T.CreateServerActionArgs<Info>
@@ -1068,68 +1064,22 @@ async function resolveViteConfig({
1068
1064
  }
1069
1065
  return viteConfig;
1070
1066
  }
1071
- async function extractPluginContext(viteConfig) {
1067
+ function extractPluginContext(viteConfig) {
1072
1068
  return viteConfig["__reactRouterPluginContext"];
1073
1069
  }
1074
1070
  function isSeverBundleEnvironmentName(name) {
1075
1071
  return name.startsWith(SSR_BUNDLE_PREFIX);
1076
1072
  }
1077
- function getServerEnvironmentEntries(record, buildManifest) {
1073
+ function getServerEnvironmentEntries(ctx, record) {
1078
1074
  return Object.entries(record).filter(
1079
- ([name]) => buildManifest.serverBundles ? isSeverBundleEnvironmentName(name) : name === "ssr"
1080
- );
1081
- }
1082
- function getServerEnvironmentKeys(record, buildManifest) {
1083
- return getServerEnvironmentEntries(record, buildManifest).map(([key]) => key);
1084
- }
1085
- function getAddressableRoutes(routes2) {
1086
- let nonAddressableIds = /* @__PURE__ */ new Set();
1087
- for (let id in routes2) {
1088
- let route = routes2[id];
1089
- if (route.index) {
1090
- invariant(
1091
- route.parentId,
1092
- `Expected index route "${route.id}" to have "parentId" set`
1093
- );
1094
- nonAddressableIds.add(route.parentId);
1095
- }
1096
- if (typeof route.path !== "string" && !route.index) {
1097
- nonAddressableIds.add(id);
1098
- }
1099
- }
1100
- return Object.values(routes2).filter(
1101
- (route) => !nonAddressableIds.has(route.id)
1075
+ ([name]) => ctx.buildManifest?.serverBundles ? isSeverBundleEnvironmentName(name) : name === "ssr"
1102
1076
  );
1103
1077
  }
1104
- function getRouteBranch(routes2, routeId) {
1105
- let branch = [];
1106
- let currentRouteId = routeId;
1107
- while (currentRouteId) {
1108
- let route = routes2[currentRouteId];
1109
- invariant(route, `Missing route for ${currentRouteId}`);
1110
- branch.push(route);
1111
- currentRouteId = route.parentId;
1112
- }
1113
- return branch.reverse();
1078
+ function getServerEnvironmentKeys(ctx, record) {
1079
+ return getServerEnvironmentEntries(ctx, record).map(([key]) => key);
1114
1080
  }
1115
- function hasServerBundles(buildManifest) {
1116
- return Object.keys(buildManifest.serverBundles ?? {}).length > 0;
1117
- }
1118
- function getRoutesByServerBundleId(buildManifest) {
1119
- if (!buildManifest.routeIdToServerBundleId) {
1120
- return {};
1121
- }
1122
- let routesByServerBundleId = {};
1123
- for (let [routeId, serverBundleId] of Object.entries(
1124
- buildManifest.routeIdToServerBundleId
1125
- )) {
1126
- routesByServerBundleId[serverBundleId] ??= {};
1127
- let branch = getRouteBranch(buildManifest.routes, routeId);
1128
- for (let route of branch) {
1129
- routesByServerBundleId[serverBundleId][route.id] = route;
1130
- }
1131
- }
1132
- return routesByServerBundleId;
1081
+ function getServerBundleIds(ctx) {
1082
+ return ctx.buildManifest?.serverBundles ? Object.keys(ctx.buildManifest.serverBundles) : void 0;
1133
1083
  }
1134
1084
  async function cleanBuildDirectory(viteConfig, ctx) {
1135
1085
  let buildDirectory = ctx.reactRouterConfig.buildDirectory;
@@ -1164,65 +1114,6 @@ async function cleanViteManifests(environmentsOptions, ctx) {
1164
1114
  })
1165
1115
  );
1166
1116
  }
1167
- async function getBuildManifest(ctx) {
1168
- let { routes: routes2, serverBundles, appDirectory } = ctx.reactRouterConfig;
1169
- if (!serverBundles) {
1170
- return { routes: routes2 };
1171
- }
1172
- let { normalizePath } = await import("vite");
1173
- let serverBuildDirectory = getServerBuildDirectory(ctx);
1174
- let resolvedAppDirectory = path7.resolve(ctx.rootDirectory, appDirectory);
1175
- let rootRelativeRoutes = Object.fromEntries(
1176
- Object.entries(routes2).map(([id, route]) => {
1177
- let filePath = path7.join(resolvedAppDirectory, route.file);
1178
- let rootRelativeFilePath = normalizePath(
1179
- path7.relative(ctx.rootDirectory, filePath)
1180
- );
1181
- return [id, { ...route, file: rootRelativeFilePath }];
1182
- })
1183
- );
1184
- let buildManifest = {
1185
- serverBundles: {},
1186
- routeIdToServerBundleId: {},
1187
- routes: rootRelativeRoutes
1188
- };
1189
- await Promise.all(
1190
- getAddressableRoutes(routes2).map(async (route) => {
1191
- let branch = getRouteBranch(routes2, route.id);
1192
- let serverBundleId = await serverBundles({
1193
- branch: branch.map(
1194
- (route2) => configRouteToBranchRoute({
1195
- ...route2,
1196
- // Ensure absolute paths are passed to the serverBundles function
1197
- file: path7.join(resolvedAppDirectory, route2.file)
1198
- })
1199
- )
1200
- });
1201
- if (typeof serverBundleId !== "string") {
1202
- throw new Error(`The "serverBundles" function must return a string`);
1203
- }
1204
- if (!/^[a-zA-Z0-9-_]+$/.test(serverBundleId)) {
1205
- throw new Error(
1206
- `The "serverBundles" function must only return strings containing alphanumeric characters, hyphens and underscores.`
1207
- );
1208
- }
1209
- buildManifest.routeIdToServerBundleId[route.id] = serverBundleId;
1210
- buildManifest.serverBundles[serverBundleId] ??= {
1211
- id: serverBundleId,
1212
- file: normalizePath(
1213
- path7.join(
1214
- path7.relative(
1215
- ctx.rootDirectory,
1216
- path7.join(serverBuildDirectory, serverBundleId)
1217
- ),
1218
- ctx.reactRouterConfig.serverBuildFile
1219
- )
1220
- )
1221
- };
1222
- })
1223
- );
1224
- return buildManifest;
1225
- }
1226
1117
  function mergeEnvironmentOptions(base, ...overrides) {
1227
1118
  let vite2 = getVite();
1228
1119
  return overrides.reduce(
@@ -1230,7 +1121,7 @@ function mergeEnvironmentOptions(base, ...overrides) {
1230
1121
  base
1231
1122
  );
1232
1123
  }
1233
- async function getEnvironmentOptionsResolvers(ctx, buildManifest, viteCommand) {
1124
+ async function getEnvironmentOptionsResolvers(ctx, viteCommand) {
1234
1125
  let { serverBuildFile, serverModuleFormat } = ctx.reactRouterConfig;
1235
1126
  let packageRoot = path7.dirname(
1236
1127
  require.resolve("@react-router/dev/package.json")
@@ -1274,7 +1165,15 @@ async function getEnvironmentOptionsResolvers(ctx, buildManifest, viteCommand) {
1274
1165
  let conditions = viteCommand === "build" ? viteServerConditions : ["development", ...viteServerConditions];
1275
1166
  return mergeEnvironmentOptions(getBaseOptions({ viteUserConfig }), {
1276
1167
  resolve: {
1277
- external: ssrExternals,
1168
+ external: (
1169
+ // This check is required to honor the "noExternal: true" config
1170
+ // provided by vite-plugin-cloudflare within this repo. When compiling
1171
+ // for Cloudflare, all server dependencies are externalized, but our
1172
+ // `ssrExternals` config inadvertently overrides this. This doesn't
1173
+ // impact consumers because for them `ssrExternals` is undefined and
1174
+ // Cloudflare's "noExternal: true" config remains intact.
1175
+ ctx.reactRouterConfig.future.unstable_viteEnvironmentApi && viteUserConfig.environments?.ssr?.resolve?.noExternal === true ? void 0 : ssrExternals
1176
+ ),
1278
1177
  conditions,
1279
1178
  externalConditions: conditions
1280
1179
  },
@@ -1288,6 +1187,7 @@ async function getEnvironmentOptionsResolvers(ctx, buildManifest, viteCommand) {
1288
1187
  copyPublicDir: false,
1289
1188
  // Assets in the public directory are only used by the client
1290
1189
  rollupOptions: {
1190
+ input: (ctx.reactRouterConfig.future.unstable_viteEnvironmentApi ? viteUserConfig.environments?.ssr?.build?.rollupOptions?.input : viteUserConfig.build?.rollupOptions?.input) ?? virtual.serverBuild.id,
1291
1191
  output: {
1292
1192
  entryFileNames: serverBuildFile,
1293
1193
  format: serverModuleFormat
@@ -1319,12 +1219,15 @@ async function getEnvironmentOptionsResolvers(ctx, buildManifest, viteCommand) {
1319
1219
  }
1320
1220
  )
1321
1221
  ],
1322
- output: {
1323
- entryFileNames({ moduleIds }) {
1222
+ output: (ctx.reactRouterConfig.future.unstable_viteEnvironmentApi ? viteUserConfig?.environments?.client?.build?.rollupOptions?.output : viteUserConfig?.build?.rollupOptions?.output) ?? {
1223
+ entryFileNames: ({ moduleIds }) => {
1324
1224
  let routeChunkModuleId = moduleIds.find(isRouteChunkModuleId);
1325
1225
  let routeChunkName = routeChunkModuleId ? getRouteChunkNameFromModuleId(routeChunkModuleId) : null;
1326
1226
  let routeChunkSuffix = routeChunkName ? `-${(0, import_kebabCase.default)(routeChunkName)}` : "";
1327
- return `assets/[name]${routeChunkSuffix}-[hash].js`;
1227
+ return path7.posix.join(
1228
+ (ctx.reactRouterConfig.future.unstable_viteEnvironmentApi ? viteUserConfig?.environments?.client?.build?.assetsDir : viteUserConfig?.build?.assetsDir) ?? "assets",
1229
+ `[name]${routeChunkSuffix}-[hash].js`
1230
+ );
1328
1231
  }
1329
1232
  }
1330
1233
  },
@@ -1332,22 +1235,17 @@ async function getEnvironmentOptionsResolvers(ctx, buildManifest, viteCommand) {
1332
1235
  }
1333
1236
  })
1334
1237
  };
1335
- if (hasServerBundles(buildManifest)) {
1336
- for (let [serverBundleId, routes2] of Object.entries(
1337
- getRoutesByServerBundleId(buildManifest)
1338
- )) {
1339
- const serverBundleEnvironmentId = serverBundleId.replaceAll("-", "_");
1340
- const environmentName = `${SSR_BUNDLE_PREFIX}${serverBundleEnvironmentId}`;
1238
+ let serverBundleIds = getServerBundleIds(ctx);
1239
+ if (serverBundleIds) {
1240
+ for (let serverBundleId of serverBundleIds) {
1241
+ const environmentName = `${SSR_BUNDLE_PREFIX}${serverBundleId}`;
1341
1242
  environmentOptionsResolvers[environmentName] = ({ viteUserConfig }) => mergeEnvironmentOptions(
1342
1243
  getBaseServerOptions({ viteUserConfig }),
1343
1244
  {
1344
1245
  build: {
1345
- outDir: getServerBuildDirectory(ctx, { serverBundleId }),
1346
- rollupOptions: {
1347
- input: `${virtual.serverBuild.id}?route-ids=${Object.keys(
1348
- routes2
1349
- ).join(",")}`
1350
- }
1246
+ outDir: getServerBuildDirectory(ctx.reactRouterConfig, {
1247
+ serverBundleId
1248
+ })
1351
1249
  }
1352
1250
  },
1353
1251
  // Ensure server bundle environments extend the user's SSR
@@ -1358,10 +1256,7 @@ async function getEnvironmentOptionsResolvers(ctx, buildManifest, viteCommand) {
1358
1256
  } else {
1359
1257
  environmentOptionsResolvers.ssr = ({ viteUserConfig }) => mergeEnvironmentOptions(getBaseServerOptions({ viteUserConfig }), {
1360
1258
  build: {
1361
- outDir: getServerBuildDirectory(ctx),
1362
- rollupOptions: {
1363
- input: (ctx.reactRouterConfig.future.unstable_viteEnvironmentApi ? viteUserConfig.environments?.ssr?.build?.rollupOptions?.input : viteUserConfig.build?.rollupOptions?.input) ?? virtual.serverBuild.id
1364
- }
1259
+ outDir: getServerBuildDirectory(ctx.reactRouterConfig)
1365
1260
  },
1366
1261
  optimizeDeps: ctx.reactRouterConfig.future.unstable_viteEnvironmentApi && viteUserConfig.environments?.ssr?.optimizeDeps?.noDiscovery === false ? {
1367
1262
  entries: [
@@ -1396,7 +1291,7 @@ function resolveEnvironmentsOptions(environmentResolvers, resolverOptions) {
1396
1291
  function isNonNullable(x) {
1397
1292
  return x != null;
1398
1293
  }
1399
- var import_node_crypto, path7, url, fse, babel2, import_react_router2, import_es_module_lexer, import_pick3, import_jsesc, import_picocolors4, import_kebabCase, BUILD_CLIENT_ROUTE_QUERY_STRING, SSR_BUNDLE_PREFIX, CSS_DEV_HELPER_ENVIRONMENT_NAME, virtualHmrRuntime, virtualInjectHmrRuntime, resolveRelativeRouteFilePath, virtual, getServerBuildDirectory, getClientBuildDirectory, defaultEntriesDir, defaultEntries, REACT_REFRESH_HEADER;
1294
+ var import_node_crypto, path7, url, fse, babel2, import_react_router2, import_es_module_lexer, import_pick3, import_jsesc, import_picocolors4, import_kebabCase, CLIENT_NON_COMPONENT_EXPORTS, CLIENT_ROUTE_EXPORTS, BUILD_CLIENT_ROUTE_QUERY_STRING, SSR_BUNDLE_PREFIX, CSS_DEV_HELPER_ENVIRONMENT_NAME, virtualHmrRuntime, virtualInjectHmrRuntime, resolveRelativeRouteFilePath, virtual, getServerBuildDirectory, getClientBuildDirectory, defaultEntriesDir, defaultEntries, REACT_REFRESH_HEADER;
1400
1295
  var init_plugin = __esm({
1401
1296
  "vite/plugin.ts"() {
1402
1297
  "use strict";
@@ -1424,6 +1319,22 @@ var init_plugin = __esm({
1424
1319
  init_vite();
1425
1320
  init_config();
1426
1321
  init_with_props();
1322
+ CLIENT_NON_COMPONENT_EXPORTS = [
1323
+ "clientAction",
1324
+ "clientLoader",
1325
+ "unstable_clientMiddleware",
1326
+ "handle",
1327
+ "meta",
1328
+ "links",
1329
+ "shouldRevalidate"
1330
+ ];
1331
+ CLIENT_ROUTE_EXPORTS = [
1332
+ ...CLIENT_NON_COMPONENT_EXPORTS,
1333
+ "default",
1334
+ "ErrorBoundary",
1335
+ "HydrateFallback",
1336
+ "Layout"
1337
+ ];
1427
1338
  BUILD_CLIENT_ROUTE_QUERY_STRING = "?__react-router-build-client-route";
1428
1339
  SSR_BUNDLE_PREFIX = "ssrBundle_";
1429
1340
  CSS_DEV_HELPER_ENVIRONMENT_NAME = "__react_router_css_dev_helper__";
@@ -1440,8 +1351,8 @@ var init_plugin = __esm({
1440
1351
  serverManifest: create("server-manifest"),
1441
1352
  browserManifest: create("browser-manifest")
1442
1353
  };
1443
- getServerBuildDirectory = (ctx, { serverBundleId } = {}) => path7.join(
1444
- ctx.reactRouterConfig.buildDirectory,
1354
+ getServerBuildDirectory = (reactRouterConfig, { serverBundleId } = {}) => path7.join(
1355
+ reactRouterConfig.buildDirectory,
1445
1356
  "server",
1446
1357
  ...serverBundleId ? [serverBundleId] : []
1447
1358
  );
@@ -1585,7 +1496,7 @@ async function viteBuild(root, {
1585
1496
  }
1586
1497
  ]
1587
1498
  });
1588
- let ctx = await extractPluginContext(viteConfig);
1499
+ let ctx = extractPluginContext(viteConfig);
1589
1500
  if (!ctx) {
1590
1501
  console.error(
1591
1502
  import_picocolors5.default.red("React Router Vite plugin not found in Vite config")
@@ -1615,14 +1526,16 @@ async function viteBuild(root, {
1615
1526
  optimizeDeps: { force },
1616
1527
  clearScreen,
1617
1528
  logLevel,
1618
- ...{ __reactRouterEnvironmentBuildContext: environmentBuildContext }
1529
+ ...{
1530
+ __reactRouterPluginContext: ctx,
1531
+ __reactRouterEnvironmentBuildContext: environmentBuildContext
1532
+ }
1619
1533
  });
1620
1534
  }
1621
- let { reactRouterConfig } = ctx;
1622
- let buildManifest = await getBuildManifest(ctx);
1535
+ let { reactRouterConfig, buildManifest } = ctx;
1536
+ invariant(buildManifest, "Expected build manifest to be present");
1623
1537
  let environmentOptionsResolvers = await getEnvironmentOptionsResolvers(
1624
1538
  ctx,
1625
- buildManifest,
1626
1539
  "build"
1627
1540
  );
1628
1541
  let environmentsOptions = resolveEnvironmentsOptions(
@@ -1632,8 +1545,8 @@ async function viteBuild(root, {
1632
1545
  await cleanBuildDirectory(viteConfig, ctx);
1633
1546
  await buildEnvironment("client");
1634
1547
  let serverEnvironmentNames = getServerEnvironmentKeys(
1635
- environmentOptionsResolvers,
1636
- buildManifest
1548
+ ctx,
1549
+ environmentOptionsResolvers
1637
1550
  );
1638
1551
  await Promise.all(serverEnvironmentNames.map(buildEnvironment));
1639
1552
  await cleanViteManifests(environmentsOptions, ctx);
package/dist/config.d.ts CHANGED
@@ -37,15 +37,19 @@ type ServerBundlesBuildManifest = BaseBuildManifest & {
37
37
  };
38
38
  type ServerModuleFormat = "esm" | "cjs";
39
39
  interface FutureConfig {
40
+ /**
41
+ * Enable route middleware
42
+ */
43
+ unstable_middleware: boolean;
40
44
  unstable_optimizeDeps: boolean;
41
45
  /**
42
46
  * Automatically split route modules into multiple chunks when possible.
43
47
  */
44
- unstable_splitRouteModules?: boolean | "enforce";
48
+ unstable_splitRouteModules: boolean | "enforce";
45
49
  /**
46
50
  * Use Vite Environment API (experimental)
47
51
  */
48
- unstable_viteEnvironmentApi?: boolean;
52
+ unstable_viteEnvironmentApi: boolean;
49
53
  }
50
54
  type BuildManifest = DefaultBuildManifest | ServerBundlesBuildManifest;
51
55
  type BuildEndHook = (args: {
package/dist/config.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @react-router/dev v0.0.0-experimental-1b454267f
2
+ * @react-router/dev v0.0.0-experimental-d499f664f
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 v0.0.0-experimental-1b454267f
2
+ * @react-router/dev v0.0.0-experimental-d499f664f
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @react-router/dev v0.0.0-experimental-1b454267f
2
+ * @react-router/dev v0.0.0-experimental-d499f664f
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -64,7 +64,18 @@ function invariant(value, message) {
64
64
  }
65
65
 
66
66
  // vite/node-adapter.ts
67
- function fromNodeHeaders(nodeHeaders) {
67
+ function fromNodeHeaders(nodeReq) {
68
+ let nodeHeaders = nodeReq.headers;
69
+ if (nodeReq.httpVersionMajor >= 2) {
70
+ nodeHeaders = { ...nodeHeaders };
71
+ if (nodeHeaders[":authority"]) {
72
+ nodeHeaders.host = nodeHeaders[":authority"];
73
+ }
74
+ delete nodeHeaders[":authority"];
75
+ delete nodeHeaders[":method"];
76
+ delete nodeHeaders[":path"];
77
+ delete nodeHeaders[":scheme"];
78
+ }
68
79
  let headers = new Headers();
69
80
  for (let [key, values] of Object.entries(nodeHeaders)) {
70
81
  if (values) {
@@ -89,7 +100,7 @@ function fromNodeRequest(nodeReq, nodeRes) {
89
100
  let controller = new AbortController();
90
101
  let init = {
91
102
  method: nodeReq.method,
92
- headers: fromNodeHeaders(nodeReq.headers),
103
+ headers: fromNodeHeaders(nodeReq),
93
104
  signal: controller.signal
94
105
  };
95
106
  nodeRes.on("finish", () => controller = null);
@@ -477,6 +488,7 @@ async function resolveConfig({
477
488
  );
478
489
  }
479
490
  let future = {
491
+ unstable_middleware: reactRouterUserConfig.future?.unstable_middleware ?? false,
480
492
  unstable_optimizeDeps: reactRouterUserConfig.future?.unstable_optimizeDeps ?? false,
481
493
  unstable_splitRouteModules: reactRouterUserConfig.future?.unstable_splitRouteModules ?? false,
482
494
  unstable_viteEnvironmentApi: reactRouterUserConfig.future?.unstable_viteEnvironmentApi ?? false
package/dist/vite.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @react-router/dev v0.0.0-experimental-1b454267f
2
+ * @react-router/dev v0.0.0-experimental-d499f664f
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -453,6 +453,7 @@ async function resolveConfig({
453
453
  );
454
454
  }
455
455
  let future = {
456
+ unstable_middleware: reactRouterUserConfig.future?.unstable_middleware ?? false,
456
457
  unstable_optimizeDeps: reactRouterUserConfig.future?.unstable_optimizeDeps ?? false,
457
458
  unstable_splitRouteModules: reactRouterUserConfig.future?.unstable_splitRouteModules ?? false,
458
459
  unstable_viteEnvironmentApi: reactRouterUserConfig.future?.unstable_viteEnvironmentApi ?? false
@@ -750,6 +751,8 @@ function generate2(ctx, route) {
750
751
  export type HeadersArgs = T.HeadersArgs
751
752
  export type HeadersFunction = (args: HeadersArgs) => Headers | HeadersInit
752
753
 
754
+ export type unstable_MiddlewareFunction = T.CreateServerMiddlewareFunction<Info>
755
+ export type unstable_ClientMiddlewareFunction = T.CreateClientMiddlewareFunction<Info>
753
756
  export type LoaderArgs = T.CreateServerLoaderArgs<Info>
754
757
  export type ClientLoaderArgs = T.CreateClientLoaderArgs<Info>
755
758
  export type ActionArgs = T.CreateServerActionArgs<Info>
@@ -867,7 +870,18 @@ var import_node_events = require("events");
867
870
  var import_node_stream = require("stream");
868
871
  var import_set_cookie_parser = require("set-cookie-parser");
869
872
  var import_node = require("@react-router/node");
870
- function fromNodeHeaders(nodeHeaders) {
873
+ function fromNodeHeaders(nodeReq) {
874
+ let nodeHeaders = nodeReq.headers;
875
+ if (nodeReq.httpVersionMajor >= 2) {
876
+ nodeHeaders = { ...nodeHeaders };
877
+ if (nodeHeaders[":authority"]) {
878
+ nodeHeaders.host = nodeHeaders[":authority"];
879
+ }
880
+ delete nodeHeaders[":authority"];
881
+ delete nodeHeaders[":method"];
882
+ delete nodeHeaders[":path"];
883
+ delete nodeHeaders[":scheme"];
884
+ }
871
885
  let headers = new Headers();
872
886
  for (let [key, values] of Object.entries(nodeHeaders)) {
873
887
  if (values) {
@@ -892,7 +906,7 @@ function fromNodeRequest(nodeReq, nodeRes) {
892
906
  let controller = new AbortController();
893
907
  let init = {
894
908
  method: nodeReq.method,
895
- headers: fromNodeHeaders(nodeReq.headers),
909
+ headers: fromNodeHeaders(nodeReq),
896
910
  signal: controller.signal
897
911
  };
898
912
  nodeRes.on("finish", () => controller = null);
@@ -1945,34 +1959,47 @@ function toFunctionExpression(decl) {
1945
1959
  }
1946
1960
 
1947
1961
  // vite/plugin.ts
1948
- var SERVER_ONLY_ROUTE_EXPORTS = ["loader", "action", "headers"];
1949
- var CLIENT_ROUTE_EXPORTS = [
1962
+ function extractPluginContext(viteConfig) {
1963
+ return viteConfig["__reactRouterPluginContext"];
1964
+ }
1965
+ var SERVER_ONLY_ROUTE_EXPORTS = [
1966
+ "loader",
1967
+ "action",
1968
+ "unstable_middleware",
1969
+ "headers"
1970
+ ];
1971
+ var CLIENT_NON_COMPONENT_EXPORTS = [
1950
1972
  "clientAction",
1951
1973
  "clientLoader",
1952
- "default",
1953
- "ErrorBoundary",
1974
+ "unstable_clientMiddleware",
1954
1975
  "handle",
1955
- "HydrateFallback",
1956
- "Layout",
1957
- "links",
1958
1976
  "meta",
1977
+ "links",
1959
1978
  "shouldRevalidate"
1960
1979
  ];
1980
+ var CLIENT_ROUTE_EXPORTS = [
1981
+ ...CLIENT_NON_COMPONENT_EXPORTS,
1982
+ "default",
1983
+ "ErrorBoundary",
1984
+ "HydrateFallback",
1985
+ "Layout"
1986
+ ];
1961
1987
  var BUILD_CLIENT_ROUTE_QUERY_STRING = "?__react-router-build-client-route";
1962
1988
  var SSR_BUNDLE_PREFIX = "ssrBundle_";
1989
+ function isSsrBundleEnvironmentName(name) {
1990
+ return name.startsWith(SSR_BUNDLE_PREFIX);
1991
+ }
1963
1992
  var CSS_DEV_HELPER_ENVIRONMENT_NAME = "__react_router_css_dev_helper__";
1964
1993
  function isSeverBundleEnvironmentName(name) {
1965
1994
  return name.startsWith(SSR_BUNDLE_PREFIX);
1966
1995
  }
1967
- function getServerEnvironmentEntries(record, buildManifest) {
1996
+ function getServerEnvironmentEntries(ctx, record) {
1968
1997
  return Object.entries(record).filter(
1969
- ([name]) => buildManifest.serverBundles ? isSeverBundleEnvironmentName(name) : name === "ssr"
1998
+ ([name]) => ctx.buildManifest?.serverBundles ? isSeverBundleEnvironmentName(name) : name === "ssr"
1970
1999
  );
1971
2000
  }
1972
- function getServerEnvironmentValues(record, buildManifest) {
1973
- return getServerEnvironmentEntries(record, buildManifest).map(
1974
- ([, value]) => value
1975
- );
2001
+ function getServerEnvironmentValues(ctx, record) {
2002
+ return getServerEnvironmentEntries(ctx, record).map(([, value]) => value);
1976
2003
  }
1977
2004
  var isRouteEntryModuleId = (id) => {
1978
2005
  return id.endsWith(BUILD_CLIENT_ROUTE_QUERY_STRING);
@@ -1980,6 +2007,23 @@ var isRouteEntryModuleId = (id) => {
1980
2007
  var isRouteVirtualModule = (id) => {
1981
2008
  return isRouteEntryModuleId(id) || isRouteChunkModuleId(id);
1982
2009
  };
2010
+ var isServerBuildVirtualModuleId = (id) => {
2011
+ return id.split("?")[0] === virtual.serverBuild.id;
2012
+ };
2013
+ var getServerBuildFile = (viteManifest) => {
2014
+ let serverBuildIds = Object.keys(viteManifest).filter(
2015
+ isServerBuildVirtualModuleId
2016
+ );
2017
+ invariant(
2018
+ serverBuildIds.length <= 1,
2019
+ "Multiple server build files found in manifest"
2020
+ );
2021
+ invariant(
2022
+ serverBuildIds.length === 1,
2023
+ "Server build file not found in manifest"
2024
+ );
2025
+ return viteManifest[serverBuildIds[0]].file;
2026
+ };
1983
2027
  var virtualHmrRuntime = create("hmr-runtime");
1984
2028
  var virtualInjectHmrRuntime = create("inject-hmr-runtime");
1985
2029
  var normalizeRelativeFilePath = (file, reactRouterConfig) => {
@@ -2146,12 +2190,29 @@ var resolveEnvironmentBuildContext = ({
2146
2190
  };
2147
2191
  return resolvedBuildContext;
2148
2192
  };
2149
- var getServerBuildDirectory = (ctx, { serverBundleId } = {}) => path6.join(
2150
- ctx.reactRouterConfig.buildDirectory,
2193
+ var getServerBuildDirectory = (reactRouterConfig, { serverBundleId } = {}) => path6.join(
2194
+ reactRouterConfig.buildDirectory,
2151
2195
  "server",
2152
2196
  ...serverBundleId ? [serverBundleId] : []
2153
2197
  );
2154
2198
  var getClientBuildDirectory = (reactRouterConfig) => path6.join(reactRouterConfig.buildDirectory, "client");
2199
+ var getServerBundleRouteIds = (vitePluginContext, ctx) => {
2200
+ if (!ctx.buildManifest) {
2201
+ return void 0;
2202
+ }
2203
+ let environmentName = ctx.reactRouterConfig.future.unstable_viteEnvironmentApi ? vitePluginContext.environment.name : ctx.environmentBuildContext?.name;
2204
+ if (!environmentName || !isSsrBundleEnvironmentName(environmentName)) {
2205
+ return void 0;
2206
+ }
2207
+ let serverBundleId = environmentName.replace(SSR_BUNDLE_PREFIX, "");
2208
+ let routesByServerBundleId = getRoutesByServerBundleId(ctx.buildManifest);
2209
+ let serverBundleRoutes = routesByServerBundleId[serverBundleId];
2210
+ invariant(
2211
+ serverBundleRoutes,
2212
+ `Routes not found for server bundle "${serverBundleId}"`
2213
+ );
2214
+ return Object.keys(serverBundleRoutes);
2215
+ };
2155
2216
  var injectQuery = (url2, query) => url2.includes("?") ? url2.replace("?", `?${query}&`) : `${url2}?${query}`;
2156
2217
  var defaultEntriesDir = path6.resolve(
2157
2218
  path6.dirname(require.resolve("@react-router/dev/package.json")),
@@ -2168,7 +2229,6 @@ var reactRouterVitePlugin = () => {
2168
2229
  let viteUserConfig;
2169
2230
  let viteConfigEnv;
2170
2231
  let viteConfig;
2171
- let buildManifest;
2172
2232
  let cssModulesManifest = {};
2173
2233
  let viteChildCompiler = null;
2174
2234
  let cache = /* @__PURE__ */ new Map();
@@ -2189,6 +2249,7 @@ var reactRouterVitePlugin = () => {
2189
2249
  }
2190
2250
  return;
2191
2251
  }
2252
+ let injectedPluginContext = !reactRouterConfig.future.unstable_viteEnvironmentApi && viteCommand === "build" ? extractPluginContext(viteUserConfig) : void 0;
2192
2253
  let { entryClientFilePath, entryServerFilePath } = await resolveEntryFiles({
2193
2254
  rootDirectory,
2194
2255
  reactRouterConfig
@@ -2203,6 +2264,7 @@ var reactRouterVitePlugin = () => {
2203
2264
  process.exit(1);
2204
2265
  }
2205
2266
  let viteManifestEnabled = viteUserConfig.build?.manifest === true;
2267
+ let buildManifest = viteCommand === "build" ? injectedPluginContext?.buildManifest ?? await getBuildManifest({ reactRouterConfig, rootDirectory }) : null;
2206
2268
  let environmentBuildContext = viteCommand === "build" ? resolveEnvironmentBuildContext({ viteCommand, viteUserConfig }) : null;
2207
2269
  firstLoad = false;
2208
2270
  ctx = {
@@ -2212,7 +2274,8 @@ var reactRouterVitePlugin = () => {
2212
2274
  entryClientFilePath,
2213
2275
  entryServerFilePath,
2214
2276
  publicPath,
2215
- viteManifestEnabled
2277
+ viteManifestEnabled,
2278
+ buildManifest
2216
2279
  };
2217
2280
  };
2218
2281
  let pluginIndex = (pluginName) => {
@@ -2234,21 +2297,26 @@ var reactRouterVitePlugin = () => {
2234
2297
  ctx.reactRouterConfig.ssr,
2235
2298
  routes
2236
2299
  );
2300
+ let isSpaMode = isSpaModeEnabled(ctx.reactRouterConfig);
2237
2301
  return `
2238
- import * as entryServer from ${JSON.stringify(
2302
+ import * as entryServer from ${JSON.stringify(
2239
2303
  resolveFileUrl(ctx, ctx.entryServerFilePath)
2240
2304
  )};
2241
- ${Object.keys(routes).map((key, index) => {
2305
+ ${Object.keys(routes).map((key, index) => {
2242
2306
  let route = routes[key];
2243
- return `import * as route${index} from ${JSON.stringify(
2244
- resolveFileUrl(
2245
- ctx,
2246
- resolveRelativeRouteFilePath(route, ctx.reactRouterConfig)
2247
- )
2248
- )};`;
2307
+ if (isSpaMode && key !== "root") {
2308
+ return `const route${index} = { default: () => null };`;
2309
+ } else {
2310
+ return `import * as route${index} from ${JSON.stringify(
2311
+ resolveFileUrl(
2312
+ ctx,
2313
+ resolveRelativeRouteFilePath(route, ctx.reactRouterConfig)
2314
+ )
2315
+ )};`;
2316
+ }
2249
2317
  }).join("\n")}
2250
2318
  export { default as assets } from ${JSON.stringify(
2251
- `${virtual.serverManifest.id}${routeIds ? `?route-ids=${routeIds.join(",")}` : ""}`
2319
+ virtual.serverManifest.id
2252
2320
  )};
2253
2321
  export const assetsBuildDirectory = ${JSON.stringify(
2254
2322
  path6.relative(
@@ -2259,7 +2327,7 @@ var reactRouterVitePlugin = () => {
2259
2327
  export const basename = ${JSON.stringify(ctx.reactRouterConfig.basename)};
2260
2328
  export const future = ${JSON.stringify(ctx.reactRouterConfig.future)};
2261
2329
  export const ssr = ${ctx.reactRouterConfig.ssr};
2262
- export const isSpaMode = ${isSpaModeEnabled(ctx.reactRouterConfig)};
2330
+ export const isSpaMode = ${isSpaMode};
2263
2331
  export const prerender = ${JSON.stringify(prerenderPaths)};
2264
2332
  export const publicPath = ${JSON.stringify(ctx.publicPath)};
2265
2333
  export const entry = { module: entryServer };
@@ -2553,7 +2621,6 @@ var reactRouterVitePlugin = () => {
2553
2621
  watch: viteCommand === "serve"
2554
2622
  });
2555
2623
  await updatePluginContext();
2556
- buildManifest = await getBuildManifest(ctx);
2557
2624
  Object.assign(
2558
2625
  process.env,
2559
2626
  vite2.loadEnv(
@@ -2565,15 +2632,12 @@ var reactRouterVitePlugin = () => {
2565
2632
  ""
2566
2633
  )
2567
2634
  );
2568
- let environments = await getEnvironmentsOptions(
2569
- ctx,
2570
- buildManifest,
2571
- viteCommand,
2572
- { viteUserConfig }
2573
- );
2635
+ let environments = await getEnvironmentsOptions(ctx, viteCommand, {
2636
+ viteUserConfig
2637
+ });
2574
2638
  let serverEnvironment = getServerEnvironmentValues(
2575
- environments,
2576
- buildManifest
2639
+ ctx,
2640
+ environments
2577
2641
  )[0];
2578
2642
  invariant(serverEnvironment);
2579
2643
  let clientEnvironment = environments.client;
@@ -2644,7 +2708,6 @@ var reactRouterVitePlugin = () => {
2644
2708
  sharedPlugins: true,
2645
2709
  async buildApp(builder) {
2646
2710
  invariant(viteConfig);
2647
- invariant(buildManifest);
2648
2711
  viteConfig.logger.info(
2649
2712
  "Using Vite Environment API (experimental)"
2650
2713
  );
@@ -2652,11 +2715,13 @@ var reactRouterVitePlugin = () => {
2652
2715
  await cleanBuildDirectory(viteConfig, ctx);
2653
2716
  await builder.build(builder.environments.client);
2654
2717
  let serverEnvironments = getServerEnvironmentValues(
2655
- builder.environments,
2656
- buildManifest
2718
+ ctx,
2719
+ builder.environments
2657
2720
  );
2658
2721
  await Promise.all(serverEnvironments.map(builder.build));
2659
2722
  await cleanViteManifests(environments, ctx);
2723
+ let { buildManifest } = ctx;
2724
+ invariant(buildManifest, "Expected build manifest");
2660
2725
  await reactRouterConfig.buildEnd?.({
2661
2726
  buildManifest,
2662
2727
  reactRouterConfig,
@@ -2840,9 +2905,21 @@ var reactRouterVitePlugin = () => {
2840
2905
  if (!viteDevServer.config.server.middlewareMode) {
2841
2906
  viteDevServer.middlewares.use(async (req, res, next) => {
2842
2907
  try {
2843
- let build = await viteDevServer.ssrLoadModule(
2844
- virtual.serverBuild.id
2845
- );
2908
+ let build;
2909
+ if (ctx.reactRouterConfig.future.unstable_viteEnvironmentApi) {
2910
+ let vite2 = getVite();
2911
+ let ssrEnvironment = viteDevServer.environments.ssr;
2912
+ if (!vite2.isRunnableDevEnvironment(ssrEnvironment)) {
2913
+ return;
2914
+ }
2915
+ build = await ssrEnvironment.runner.import(
2916
+ virtual.serverBuild.id
2917
+ );
2918
+ } else {
2919
+ build = await viteDevServer.ssrLoadModule(
2920
+ virtual.serverBuild.id
2921
+ );
2922
+ }
2846
2923
  let handler = (0, import_react_router2.createRequestHandler)(build, "development");
2847
2924
  let nodeHandler = async (nodeReq, nodeRes) => {
2848
2925
  let req2 = fromNodeRequest(nodeReq, nodeRes);
@@ -2872,7 +2949,7 @@ var reactRouterVitePlugin = () => {
2872
2949
  let clientBuildDirectory = getClientBuildDirectory(
2873
2950
  ctx.reactRouterConfig
2874
2951
  );
2875
- let serverBuildDirectory = future.unstable_viteEnvironmentApi ? this.environment.config?.build?.outDir : ctx.environmentBuildContext?.options.build?.outDir ?? getServerBuildDirectory(ctx);
2952
+ let serverBuildDirectory = future.unstable_viteEnvironmentApi ? this.environment.config?.build?.outDir : ctx.environmentBuildContext?.options.build?.outDir ?? getServerBuildDirectory(ctx.reactRouterConfig);
2876
2953
  let ssrViteManifest = await loadViteManifest(serverBuildDirectory);
2877
2954
  let ssrAssetPaths = getViteManifestAssetPaths(ssrViteManifest);
2878
2955
  let movedAssetPaths = [];
@@ -2911,7 +2988,7 @@ var reactRouterVitePlugin = () => {
2911
2988
  viteConfig,
2912
2989
  ctx.reactRouterConfig,
2913
2990
  serverBuildDirectory,
2914
- ssrViteManifest[virtual.serverBuild.id].file,
2991
+ getServerBuildFile(ssrViteManifest),
2915
2992
  clientBuildDirectory
2916
2993
  );
2917
2994
  }
@@ -2920,7 +2997,7 @@ var reactRouterVitePlugin = () => {
2920
2997
  viteConfig,
2921
2998
  ctx.reactRouterConfig,
2922
2999
  serverBuildDirectory,
2923
- ssrViteManifest[virtual.serverBuild.id].file,
3000
+ getServerBuildFile(ssrViteManifest),
2924
3001
  clientBuildDirectory
2925
3002
  );
2926
3003
  }
@@ -3061,22 +3138,17 @@ var reactRouterVitePlugin = () => {
3061
3138
  name: "react-router:virtual-modules",
3062
3139
  enforce: "pre",
3063
3140
  resolveId(id) {
3064
- let [baseId, queryString] = id.split("?");
3065
- const vmod2 = Object.values(virtual).find((vmod3) => vmod3.id === baseId);
3066
- if (vmod2)
3067
- return vmod2.resolvedId + (queryString ? `?${queryString}` : "");
3141
+ const vmod2 = Object.values(virtual).find((vmod3) => vmod3.id === id);
3142
+ if (vmod2) return vmod2.resolvedId;
3068
3143
  },
3069
3144
  async load(id) {
3070
- let [baseId, queryString] = id.split("?");
3071
- switch (baseId) {
3145
+ switch (id) {
3072
3146
  case virtual.serverBuild.resolvedId: {
3073
- let searchParams = new URLSearchParams(queryString);
3074
- let routeIds = searchParams.get("route-ids")?.split(",") || void 0;
3147
+ let routeIds = getServerBundleRouteIds(this, ctx);
3075
3148
  return await getServerEntry({ routeIds });
3076
3149
  }
3077
3150
  case virtual.serverManifest.resolvedId: {
3078
- let searchParams = new URLSearchParams(queryString);
3079
- let routeIds = searchParams.get("route-ids")?.split(",") || void 0;
3151
+ let routeIds = getServerBundleRouteIds(this, ctx);
3080
3152
  let reactRouterManifest = viteCommand === "build" ? (await generateReactRouterManifestsForBuild({
3081
3153
  routeIds
3082
3154
  })).reactRouterServerManifest : await getReactRouterManifestForDev();
@@ -3391,14 +3463,7 @@ function uniqueNodes(nodes) {
3391
3463
  }
3392
3464
  function addRefreshWrapper(reactRouterConfig, code, id) {
3393
3465
  let route = getRoute(reactRouterConfig, id);
3394
- let acceptExports = route ? [
3395
- "clientAction",
3396
- "clientLoader",
3397
- "handle",
3398
- "meta",
3399
- "links",
3400
- "shouldRevalidate"
3401
- ] : [];
3466
+ let acceptExports = route ? CLIENT_NON_COMPONENT_EXPORTS : [];
3402
3467
  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));
3403
3468
  }
3404
3469
  var REACT_REFRESH_HEADER = `
@@ -3563,18 +3628,26 @@ async function handlePrerender(viteConfig, reactRouterConfig, serverBuildDirecto
3563
3628
  serverBuildDirectory,
3564
3629
  serverBuildPath
3565
3630
  );
3566
- let routes = createPrerenderRoutes(build.routes);
3631
+ let routes = createPrerenderRoutes(reactRouterConfig.routes);
3632
+ for (let path7 of build.prerender) {
3633
+ let matches = (0, import_react_router2.matchRoutes)(routes, `/${path7}/`.replace(/^\/\/+/, "/"));
3634
+ if (!matches) {
3635
+ throw new Error(
3636
+ `Unable to prerender path because it does not match any routes: ${path7}`
3637
+ );
3638
+ }
3639
+ }
3640
+ let buildRoutes = createPrerenderRoutes(build.routes);
3567
3641
  let headers = {
3568
3642
  // Header that can be used in the loader to know if you're running at
3569
3643
  // build time or runtime
3570
3644
  "X-React-Router-Prerender": "yes"
3571
3645
  };
3572
3646
  for (let path7 of build.prerender) {
3573
- let matches = (0, import_react_router2.matchRoutes)(routes, `/${path7}/`.replace(/^\/\/+/, "/"));
3574
- invariant(
3575
- matches,
3576
- `Unable to prerender path because it does not match any routes: ${path7}`
3577
- );
3647
+ let matches = (0, import_react_router2.matchRoutes)(buildRoutes, `/${path7}/`.replace(/^\/\/+/, "/"));
3648
+ if (!matches) {
3649
+ continue;
3650
+ }
3578
3651
  let leafRoute = matches ? matches[matches.length - 1].route : null;
3579
3652
  let manifestRoute = leafRoute ? build.routes[leafRoute.id]?.module : null;
3580
3653
  let isResourceRoute = manifestRoute && !manifestRoute.default && !manifestRoute.ErrorBoundary;
@@ -3877,8 +3950,8 @@ function getRouteBranch(routes, routeId) {
3877
3950
  }
3878
3951
  return branch.reverse();
3879
3952
  }
3880
- function hasServerBundles(buildManifest) {
3881
- return Object.keys(buildManifest.serverBundles ?? {}).length > 0;
3953
+ function getServerBundleIds(ctx) {
3954
+ return ctx.buildManifest?.serverBundles ? Object.keys(ctx.buildManifest.serverBundles) : void 0;
3882
3955
  }
3883
3956
  function getRoutesByServerBundleId(buildManifest) {
3884
3957
  if (!buildManifest.routeIdToServerBundleId) {
@@ -3993,19 +4066,22 @@ async function cleanViteManifests(environmentsOptions, ctx) {
3993
4066
  })
3994
4067
  );
3995
4068
  }
3996
- async function getBuildManifest(ctx) {
3997
- let { routes, serverBundles, appDirectory } = ctx.reactRouterConfig;
4069
+ async function getBuildManifest({
4070
+ reactRouterConfig,
4071
+ rootDirectory
4072
+ }) {
4073
+ let { routes, serverBundles, appDirectory } = reactRouterConfig;
3998
4074
  if (!serverBundles) {
3999
4075
  return { routes };
4000
4076
  }
4001
4077
  let { normalizePath } = await import("vite");
4002
- let serverBuildDirectory = getServerBuildDirectory(ctx);
4003
- let resolvedAppDirectory = path6.resolve(ctx.rootDirectory, appDirectory);
4078
+ let serverBuildDirectory = getServerBuildDirectory(reactRouterConfig);
4079
+ let resolvedAppDirectory = path6.resolve(rootDirectory, appDirectory);
4004
4080
  let rootRelativeRoutes = Object.fromEntries(
4005
4081
  Object.entries(routes).map(([id, route]) => {
4006
4082
  let filePath = path6.join(resolvedAppDirectory, route.file);
4007
4083
  let rootRelativeFilePath = normalizePath(
4008
- path6.relative(ctx.rootDirectory, filePath)
4084
+ path6.relative(rootDirectory, filePath)
4009
4085
  );
4010
4086
  return [id, { ...route, file: rootRelativeFilePath }];
4011
4087
  })
@@ -4030,10 +4106,18 @@ async function getBuildManifest(ctx) {
4030
4106
  if (typeof serverBundleId !== "string") {
4031
4107
  throw new Error(`The "serverBundles" function must return a string`);
4032
4108
  }
4033
- if (!/^[a-zA-Z0-9-_]+$/.test(serverBundleId)) {
4034
- throw new Error(
4035
- `The "serverBundles" function must only return strings containing alphanumeric characters, hyphens and underscores.`
4036
- );
4109
+ if (reactRouterConfig.future.unstable_viteEnvironmentApi) {
4110
+ if (!/^[a-zA-Z0-9_]+$/.test(serverBundleId)) {
4111
+ throw new Error(
4112
+ `The "serverBundles" function must only return strings containing alphanumeric characters and underscores.`
4113
+ );
4114
+ }
4115
+ } else {
4116
+ if (!/^[a-zA-Z0-9-_]+$/.test(serverBundleId)) {
4117
+ throw new Error(
4118
+ `The "serverBundles" function must only return strings containing alphanumeric characters, hyphens and underscores.`
4119
+ );
4120
+ }
4037
4121
  }
4038
4122
  buildManifest.routeIdToServerBundleId[route.id] = serverBundleId;
4039
4123
  buildManifest.serverBundles[serverBundleId] ??= {
@@ -4041,10 +4125,10 @@ async function getBuildManifest(ctx) {
4041
4125
  file: normalizePath(
4042
4126
  path6.join(
4043
4127
  path6.relative(
4044
- ctx.rootDirectory,
4128
+ rootDirectory,
4045
4129
  path6.join(serverBuildDirectory, serverBundleId)
4046
4130
  ),
4047
- ctx.reactRouterConfig.serverBuildFile
4131
+ reactRouterConfig.serverBuildFile
4048
4132
  )
4049
4133
  )
4050
4134
  };
@@ -4059,7 +4143,7 @@ function mergeEnvironmentOptions(base, ...overrides) {
4059
4143
  base
4060
4144
  );
4061
4145
  }
4062
- async function getEnvironmentOptionsResolvers(ctx, buildManifest, viteCommand) {
4146
+ async function getEnvironmentOptionsResolvers(ctx, viteCommand) {
4063
4147
  let { serverBuildFile, serverModuleFormat } = ctx.reactRouterConfig;
4064
4148
  let packageRoot = path6.dirname(
4065
4149
  require.resolve("@react-router/dev/package.json")
@@ -4103,7 +4187,15 @@ async function getEnvironmentOptionsResolvers(ctx, buildManifest, viteCommand) {
4103
4187
  let conditions = viteCommand === "build" ? viteServerConditions : ["development", ...viteServerConditions];
4104
4188
  return mergeEnvironmentOptions(getBaseOptions({ viteUserConfig }), {
4105
4189
  resolve: {
4106
- external: ssrExternals,
4190
+ external: (
4191
+ // This check is required to honor the "noExternal: true" config
4192
+ // provided by vite-plugin-cloudflare within this repo. When compiling
4193
+ // for Cloudflare, all server dependencies are externalized, but our
4194
+ // `ssrExternals` config inadvertently overrides this. This doesn't
4195
+ // impact consumers because for them `ssrExternals` is undefined and
4196
+ // Cloudflare's "noExternal: true" config remains intact.
4197
+ ctx.reactRouterConfig.future.unstable_viteEnvironmentApi && viteUserConfig.environments?.ssr?.resolve?.noExternal === true ? void 0 : ssrExternals
4198
+ ),
4107
4199
  conditions,
4108
4200
  externalConditions: conditions
4109
4201
  },
@@ -4117,6 +4209,7 @@ async function getEnvironmentOptionsResolvers(ctx, buildManifest, viteCommand) {
4117
4209
  copyPublicDir: false,
4118
4210
  // Assets in the public directory are only used by the client
4119
4211
  rollupOptions: {
4212
+ input: (ctx.reactRouterConfig.future.unstable_viteEnvironmentApi ? viteUserConfig.environments?.ssr?.build?.rollupOptions?.input : viteUserConfig.build?.rollupOptions?.input) ?? virtual.serverBuild.id,
4120
4213
  output: {
4121
4214
  entryFileNames: serverBuildFile,
4122
4215
  format: serverModuleFormat
@@ -4148,12 +4241,15 @@ async function getEnvironmentOptionsResolvers(ctx, buildManifest, viteCommand) {
4148
4241
  }
4149
4242
  )
4150
4243
  ],
4151
- output: {
4152
- entryFileNames({ moduleIds }) {
4244
+ output: (ctx.reactRouterConfig.future.unstable_viteEnvironmentApi ? viteUserConfig?.environments?.client?.build?.rollupOptions?.output : viteUserConfig?.build?.rollupOptions?.output) ?? {
4245
+ entryFileNames: ({ moduleIds }) => {
4153
4246
  let routeChunkModuleId = moduleIds.find(isRouteChunkModuleId);
4154
4247
  let routeChunkName = routeChunkModuleId ? getRouteChunkNameFromModuleId(routeChunkModuleId) : null;
4155
4248
  let routeChunkSuffix = routeChunkName ? `-${(0, import_kebabCase.default)(routeChunkName)}` : "";
4156
- return `assets/[name]${routeChunkSuffix}-[hash].js`;
4249
+ return path6.posix.join(
4250
+ (ctx.reactRouterConfig.future.unstable_viteEnvironmentApi ? viteUserConfig?.environments?.client?.build?.assetsDir : viteUserConfig?.build?.assetsDir) ?? "assets",
4251
+ `[name]${routeChunkSuffix}-[hash].js`
4252
+ );
4157
4253
  }
4158
4254
  }
4159
4255
  },
@@ -4161,22 +4257,17 @@ async function getEnvironmentOptionsResolvers(ctx, buildManifest, viteCommand) {
4161
4257
  }
4162
4258
  })
4163
4259
  };
4164
- if (hasServerBundles(buildManifest)) {
4165
- for (let [serverBundleId, routes] of Object.entries(
4166
- getRoutesByServerBundleId(buildManifest)
4167
- )) {
4168
- const serverBundleEnvironmentId = serverBundleId.replaceAll("-", "_");
4169
- const environmentName = `${SSR_BUNDLE_PREFIX}${serverBundleEnvironmentId}`;
4260
+ let serverBundleIds = getServerBundleIds(ctx);
4261
+ if (serverBundleIds) {
4262
+ for (let serverBundleId of serverBundleIds) {
4263
+ const environmentName = `${SSR_BUNDLE_PREFIX}${serverBundleId}`;
4170
4264
  environmentOptionsResolvers[environmentName] = ({ viteUserConfig }) => mergeEnvironmentOptions(
4171
4265
  getBaseServerOptions({ viteUserConfig }),
4172
4266
  {
4173
4267
  build: {
4174
- outDir: getServerBuildDirectory(ctx, { serverBundleId }),
4175
- rollupOptions: {
4176
- input: `${virtual.serverBuild.id}?route-ids=${Object.keys(
4177
- routes
4178
- ).join(",")}`
4179
- }
4268
+ outDir: getServerBuildDirectory(ctx.reactRouterConfig, {
4269
+ serverBundleId
4270
+ })
4180
4271
  }
4181
4272
  },
4182
4273
  // Ensure server bundle environments extend the user's SSR
@@ -4187,10 +4278,7 @@ async function getEnvironmentOptionsResolvers(ctx, buildManifest, viteCommand) {
4187
4278
  } else {
4188
4279
  environmentOptionsResolvers.ssr = ({ viteUserConfig }) => mergeEnvironmentOptions(getBaseServerOptions({ viteUserConfig }), {
4189
4280
  build: {
4190
- outDir: getServerBuildDirectory(ctx),
4191
- rollupOptions: {
4192
- input: (ctx.reactRouterConfig.future.unstable_viteEnvironmentApi ? viteUserConfig.environments?.ssr?.build?.rollupOptions?.input : viteUserConfig.build?.rollupOptions?.input) ?? virtual.serverBuild.id
4193
- }
4281
+ outDir: getServerBuildDirectory(ctx.reactRouterConfig)
4194
4282
  },
4195
4283
  optimizeDeps: ctx.reactRouterConfig.future.unstable_viteEnvironmentApi && viteUserConfig.environments?.ssr?.optimizeDeps?.noDiscovery === false ? {
4196
4284
  entries: [
@@ -4222,10 +4310,9 @@ function resolveEnvironmentsOptions(environmentResolvers, resolverOptions) {
4222
4310
  }
4223
4311
  return environmentOptions;
4224
4312
  }
4225
- async function getEnvironmentsOptions(ctx, buildManifest, viteCommand, resolverOptions) {
4313
+ async function getEnvironmentsOptions(ctx, viteCommand, resolverOptions) {
4226
4314
  let environmentOptionsResolvers = await getEnvironmentOptionsResolvers(
4227
4315
  ctx,
4228
- buildManifest,
4229
4316
  viteCommand
4230
4317
  );
4231
4318
  return resolveEnvironmentsOptions(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@react-router/dev",
3
- "version": "0.0.0-experimental-1b454267f",
3
+ "version": "0.0.0-experimental-d499f664f",
4
4
  "description": "Dev tools and CLI for React Router",
5
5
  "homepage": "https://reactrouter.com",
6
6
  "bugs": {
@@ -88,7 +88,7 @@
88
88
  "set-cookie-parser": "^2.6.0",
89
89
  "valibot": "^0.41.0",
90
90
  "vite-node": "3.0.0-beta.2",
91
- "@react-router/node": "0.0.0-experimental-1b454267f"
91
+ "@react-router/node": "0.0.0-experimental-d499f664f"
92
92
  },
93
93
  "devDependencies": {
94
94
  "@types/babel__core": "^7.20.5",
@@ -114,18 +114,18 @@
114
114
  "tiny-invariant": "^1.2.0",
115
115
  "tsup": "^8.3.0",
116
116
  "typescript": "^5.1.6",
117
- "vite": "^6.0.0",
117
+ "vite": "^6.1.0",
118
118
  "wireit": "0.14.9",
119
- "wrangler": "^3.28.2",
120
- "@react-router/serve": "0.0.0-experimental-1b454267f",
121
- "react-router": "^0.0.0-experimental-1b454267f"
119
+ "wrangler": "^3.109.2",
120
+ "@react-router/serve": "0.0.0-experimental-d499f664f",
121
+ "react-router": "^0.0.0-experimental-d499f664f"
122
122
  },
123
123
  "peerDependencies": {
124
124
  "typescript": "^5.1.0",
125
125
  "vite": "^5.1.0 || ^6.0.0",
126
126
  "wrangler": "^3.28.2",
127
- "@react-router/serve": "^0.0.0-experimental-1b454267f",
128
- "react-router": "^0.0.0-experimental-1b454267f"
127
+ "@react-router/serve": "^0.0.0-experimental-d499f664f",
128
+ "react-router": "^0.0.0-experimental-d499f664f"
129
129
  },
130
130
  "peerDependenciesMeta": {
131
131
  "@react-router/serve": {