@react-router/dev 0.0.0-experimental-7b411a741 → 0.0.0-experimental-4ed3f5da9

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.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @react-router/dev v0.0.0-experimental-7b411a741
2
+ * @react-router/dev v0.0.0-experimental-4ed3f5da9
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -18,12 +18,11 @@ var url = require('node:url');
18
18
  var fse = require('fs-extra');
19
19
  var babel = require('@babel/core');
20
20
  var serverRuntime = require('@react-router/server-runtime');
21
+ var reactRouter = require('react-router');
21
22
  var esModuleLexer = require('es-module-lexer');
22
23
  var jsesc = require('jsesc');
23
- var pick = require('lodash/pick');
24
- var omit = require('lodash/omit');
25
24
  var colors = require('picocolors');
26
- var config = require('../config.js');
25
+ var findConfig = require('../config/findConfig.js');
27
26
  var invariant = require('../invariant.js');
28
27
  var nodeAdapter = require('./node-adapter.js');
29
28
  var styles = require('./styles.js');
@@ -31,6 +30,7 @@ var vmod = require('./vmod.js');
31
30
  var resolveFileUrl = require('./resolve-file-url.js');
32
31
  var removeExports = require('./remove-exports.js');
33
32
  var importViteEsmSync = require('./import-vite-esm-sync.js');
33
+ var config = require('../config.js');
34
34
 
35
35
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
36
36
 
@@ -57,8 +57,6 @@ var url__namespace = /*#__PURE__*/_interopNamespace(url);
57
57
  var fse__namespace = /*#__PURE__*/_interopNamespace(fse);
58
58
  var babel__default = /*#__PURE__*/_interopDefaultLegacy(babel);
59
59
  var jsesc__default = /*#__PURE__*/_interopDefaultLegacy(jsesc);
60
- var pick__default = /*#__PURE__*/_interopDefaultLegacy(pick);
61
- var omit__default = /*#__PURE__*/_interopDefaultLegacy(omit);
62
60
  var colors__default = /*#__PURE__*/_interopDefaultLegacy(colors);
63
61
 
64
62
  async function resolveViteConfig({
@@ -92,7 +90,7 @@ async function loadPluginContext({
92
90
  if (!root) {
93
91
  root = process.env.REACT_ROUTER_ROOT || process.cwd();
94
92
  }
95
- configFile = configFile ?? config.findConfig(root, "vite.config", [".ts", ".cts", ".mts", ".js", ".cjs", ".mjs"]);
93
+ configFile = configFile ?? findConfig.findConfig(root, "vite.config", [".ts", ".cts", ".mts", ".js", ".cjs", ".mjs"]);
96
94
  if (!configFile) {
97
95
  console.error(colors__default["default"].red("Vite config file not found"));
98
96
  process.exit(1);
@@ -113,10 +111,6 @@ const CLIENT_ROUTE_EXPORTS = ["clientAction", "clientLoader", "default", "ErrorB
113
111
  // The "=1" suffix ensures client route requests can be processed before hitting
114
112
  // the Vite plugin since "?client-route" can be serialized as "?client-route="
115
113
  const CLIENT_ROUTE_QUERY_STRING = "?client-route=1";
116
- // Only expose a subset of route properties to the "serverBundles" function
117
- const branchRouteProperties = ["id", "path", "file", "index"];
118
- const configRouteToBranchRoute = configRoute => pick__default["default"](configRoute, branchRouteProperties);
119
- const excludedConfigPresetKeys = ["presets"];
120
114
  let serverBuildId = vmod.id("server-build");
121
115
  let serverManifestId = vmod.id("server-manifest");
122
116
  let browserManifestId = vmod.id("browser-manifest");
@@ -244,44 +238,6 @@ let getClientBuildDirectory = reactRouterConfig => path__namespace.join(reactRou
244
238
  let defaultEntriesDir = path__namespace.resolve(__dirname, "..", "config", "defaults");
245
239
  let defaultEntries = fse__namespace.readdirSync(defaultEntriesDir).map(filename => path__namespace.join(defaultEntriesDir, filename));
246
240
  invariant["default"](defaultEntries.length > 0, "No default entries found");
247
- let mergeReactRouterConfig = (...configs) => {
248
- let reducer = (configA, configB) => {
249
- let mergeRequired = key => configA[key] !== undefined && configB[key] !== undefined;
250
- return {
251
- ...configA,
252
- ...configB,
253
- ...(mergeRequired("buildEnd") ? {
254
- buildEnd: async (...args) => {
255
- var _configA$buildEnd, _configB$buildEnd;
256
- await Promise.all([(_configA$buildEnd = configA.buildEnd) === null || _configA$buildEnd === void 0 ? void 0 : _configA$buildEnd.call(configA, ...args), (_configB$buildEnd = configB.buildEnd) === null || _configB$buildEnd === void 0 ? void 0 : _configB$buildEnd.call(configB, ...args)]);
257
- }
258
- } : {}),
259
- ...(mergeRequired("future") ? {
260
- future: {
261
- ...configA.future,
262
- ...configB.future
263
- }
264
- } : {}),
265
- ...(mergeRequired("ignoredRouteFiles") ? {
266
- ignoredRouteFiles: Array.from(new Set([...(configA.ignoredRouteFiles ?? []), ...(configB.ignoredRouteFiles ?? [])]))
267
- } : {}),
268
- ...(mergeRequired("presets") ? {
269
- presets: [...(configA.presets ?? []), ...(configB.presets ?? [])]
270
- } : {}),
271
- ...(mergeRequired("routes") ? {
272
- routes: async (...args) => {
273
- var _configA$routes, _configB$routes;
274
- let [routesA, routesB] = await Promise.all([(_configA$routes = configA.routes) === null || _configA$routes === void 0 ? void 0 : _configA$routes.call(configA, ...args), (_configB$routes = configB.routes) === null || _configB$routes === void 0 ? void 0 : _configB$routes.call(configB, ...args)]);
275
- return {
276
- ...routesA,
277
- ...routesB
278
- };
279
- }
280
- } : {})
281
- };
282
- };
283
- return configs.reduce(reducer, {});
284
- };
285
241
  let reactRouterDevLoadContext = () => ({});
286
242
  let setReactRouterDevLoadContext = loadContext => {
287
243
  reactRouterDevLoadContext = loadContext;
@@ -315,86 +271,21 @@ const reactRouterVitePlugin = _config => {
315
271
  let ctx;
316
272
  /** Mutates `ctx` as a side-effect */
317
273
  let updatePluginContext = async () => {
318
- var _viteUserConfig$serve, _viteUserConfig$build;
319
- let presets = (await Promise.all((reactRouterUserConfig.presets ?? []).map(async preset => {
320
- if (!preset.name) {
321
- throw new Error("React Router presets must have a `name` property defined.");
322
- }
323
- if (!preset.reactRouterConfig) {
324
- return null;
325
- }
326
- let configPreset = omit__default["default"](await preset.reactRouterConfig({
327
- reactRouterUserConfig
328
- }), excludedConfigPresetKeys);
329
- return configPreset;
330
- }))).filter(function isNotNull(value) {
331
- return value !== null;
332
- });
333
- let defaults = {
334
- basename: "/",
335
- buildDirectory: "build",
336
- manifest: false,
337
- serverBuildFile: "index.js",
338
- ssr: true
339
- };
340
- let resolvedReactRouterUserConfig = {
341
- ...defaults,
342
- // Default values should be completely overridden by user/preset config, not merged
343
- ...mergeReactRouterConfig(...presets, reactRouterUserConfig)
344
- };
274
+ var _viteUserConfig$build;
345
275
  let rootDirectory = viteUserConfig.root ?? process.env.REACT_ROUTER_ROOT ?? process.cwd();
346
- let {
347
- basename,
348
- buildEnd,
349
- manifest,
350
- ssr
351
- } = resolvedReactRouterUserConfig;
352
- let isSpaMode = !ssr;
353
- let {
354
- appDirectory,
355
- entryClientFilePath,
356
- entryServerFilePath,
357
- future,
358
- routes,
359
- serverModuleFormat
360
- } = await config.resolveConfig(resolvedReactRouterUserConfig, {
276
+ let reactRouterConfig = await config.resolveReactRouterConfig({
361
277
  rootDirectory,
362
- isSpaMode
278
+ reactRouterUserConfig,
279
+ viteUserConfig,
280
+ viteCommand
363
281
  });
364
- let buildDirectory = path__namespace.resolve(rootDirectory, resolvedReactRouterUserConfig.buildDirectory);
365
282
  let {
366
- serverBuildFile,
367
- serverBundles
368
- } = resolvedReactRouterUserConfig;
369
- let publicPath = viteUserConfig.base ?? "/";
370
- if (basename !== "/" && viteCommand === "serve" && !((_viteUserConfig$serve = viteUserConfig.server) !== null && _viteUserConfig$serve !== void 0 && _viteUserConfig$serve.middlewareMode) && !basename.startsWith(publicPath)) {
371
- throw new Error("When using the React Router `basename` and the Vite `base` config, " + "the `basename` config must begin with `base` for the default " + "Vite dev server.");
372
- }
373
- // Log warning for incompatible vite config flags
374
- if (isSpaMode && serverBundles) {
375
- console.warn(colors__default["default"].yellow(colors__default["default"].bold("⚠️ SPA Mode: ") + "the `serverBundles` config is invalid with " + "`ssr:false` and will be ignored`"));
376
- serverBundles = undefined;
377
- }
378
- let reactRouterConfig = deepFreeze({
379
- appDirectory,
380
- basename,
381
- buildDirectory,
382
- buildEnd,
383
- future,
384
- manifest,
385
- publicPath,
386
- routes,
387
- serverBuildFile,
388
- serverBundles,
389
- serverModuleFormat,
390
- ssr
283
+ entryClientFilePath,
284
+ entryServerFilePath
285
+ } = await config.resolveEntryFiles({
286
+ rootDirectory,
287
+ reactRouterConfig
391
288
  });
392
- for (let preset of reactRouterUserConfig.presets ?? []) {
393
- var _preset$reactRouterCo;
394
- await ((_preset$reactRouterCo = preset.reactRouterConfigResolved) === null || _preset$reactRouterCo === void 0 ? void 0 : _preset$reactRouterCo.call(preset, {
395
- reactRouterConfig
396
- }));
397
- }
398
289
  let viteManifestEnabled = ((_viteUserConfig$build = viteUserConfig.build) === null || _viteUserConfig$build === void 0 ? void 0 : _viteUserConfig$build.manifest) === true;
399
290
  let ssrBuildCtx = viteConfigEnv.isSsrBuild && viteCommand === "build" ? {
400
291
  isSsrBuild: true,
@@ -434,7 +325,7 @@ const reactRouterVitePlugin = _config => {
434
325
  export const assetsBuildDirectory = ${JSON.stringify(path__namespace.relative(ctx.rootDirectory, getClientBuildDirectory(ctx.reactRouterConfig)))};
435
326
  export const basename = ${JSON.stringify(ctx.reactRouterConfig.basename)};
436
327
  export const future = ${JSON.stringify(ctx.reactRouterConfig.future)};
437
- export const isSpaMode = ${!ctx.reactRouterConfig.ssr};
328
+ export const isSpaMode = ${!ctx.reactRouterConfig.ssr && ctx.reactRouterConfig.prerender == null};
438
329
  export const publicPath = ${JSON.stringify(ctx.reactRouterConfig.publicPath)};
439
330
  export const entry = { module: entryServer };
440
331
  export const routes = {
@@ -455,6 +346,10 @@ const reactRouterVitePlugin = _config => {
455
346
  let manifestContents = await fse__namespace.readFile(path__namespace.resolve(directory, ".vite", "manifest.json"), "utf-8");
456
347
  return JSON.parse(manifestContents);
457
348
  };
349
+ let getViteManifestFilePaths = viteManifest => {
350
+ let filePaths = Object.values(viteManifest).map(chunk => chunk.file);
351
+ return new Set(filePaths);
352
+ };
458
353
  let getViteManifestAssetPaths = viteManifest => {
459
354
  // Get .css?url imports and CSS entry points
460
355
  let cssUrlPaths = Object.values(viteManifest).filter(chunk => chunk.file.endsWith(".css")).map(chunk => chunk.file);
@@ -563,7 +458,7 @@ const reactRouterVitePlugin = _config => {
563
458
  return [{
564
459
  name: "react-router",
565
460
  config: async (_viteUserConfig, _viteConfigEnv) => {
566
- var _viteUserConfig$serve2, _viteUserConfig$serve3, _viteUserConfig$build4;
461
+ var _viteUserConfig$serve, _viteUserConfig$serve2, _viteUserConfig$build4;
567
462
  // Preload Vite's ESM build up-front as soon as we're in an async context
568
463
  await importViteEsmSync.preloadViteEsm();
569
464
  // Ensure sync import of Vite works after async preload
@@ -596,11 +491,11 @@ const reactRouterVitePlugin = _config => {
596
491
  __reactRouterPluginContext: ctx,
597
492
  appType: viteCommand === "serve" && viteConfigEnv.mode === "production" && ctx.reactRouterConfig.ssr === false ? "spa" : "custom",
598
493
  ssr: {
599
- external: [
600
- // This is only necessary for development within this repo
601
- // because these packages are symlinked and Vite treats them as
602
- // internal source code. For consumers this is a no-op.
603
- "react-router", "react-router-dom", "@react-router/architect", "@react-router/cloudflare-pages", "@react-router/cloudflare-workers", "@react-router/cloudflare", "@react-router/deno", "@react-router/dev", "@react-router/express", "@react-router/netlify", "@react-router/node", "@react-router/serve", "@react-router/server-runtime"]
494
+ external: isInReactRouterMonorepo() ? [
495
+ // This is only needed within this repo because these packages
496
+ // are linked to a directory outside of node_modules so Vite
497
+ // treats them as internal code by default.
498
+ "react-router", "react-router-dom", "@react-router/architect", "@react-router/cloudflare-pages", "@react-router/cloudflare-workers", "@react-router/cloudflare", "@react-router/deno", "@react-router/dev", "@react-router/express", "@react-router/netlify", "@react-router/node", "@react-router/serve", "@react-router/server-runtime"] : undefined
604
499
  },
605
500
  optimizeDeps: {
606
501
  include: [
@@ -610,13 +505,7 @@ const reactRouterVitePlugin = _config => {
610
505
  "react", "react/jsx-runtime", "react/jsx-dev-runtime", "react-dom/client",
611
506
  // Pre-bundle router dependencies to avoid router duplicates.
612
507
  // Mismatching routers cause `Error: You must render this element inside a <Remix> element`.
613
- "react-router", "react-router-dom",
614
- // For some reason, the `vite-dotenv` integration test consistently fails on webkit
615
- // with `504 (Outdated Optimize Dep)` from Vite unless `@react-router/node` is included
616
- // in `optimizeDeps.include`. 🤷
617
- // This could be caused by how we copy `node_modules/` into integration test fixtures,
618
- // so maybe this will be unnecessary once we switch to pnpm
619
- "@react-router/node"]
508
+ "react-router", "react-router-dom"]
620
509
  },
621
510
  esbuild: {
622
511
  jsx: "automatic",
@@ -635,7 +524,7 @@ const reactRouterVitePlugin = _config => {
635
524
  // If we don't do this and a default entry file is used, the server
636
525
  // will throw an error that the file is not allowed to be read.
637
526
  // https://vitejs.dev/config/server-options#server-fs-allow
638
- server: (_viteUserConfig$serve2 = viteUserConfig.server) !== null && _viteUserConfig$serve2 !== void 0 && (_viteUserConfig$serve3 = _viteUserConfig$serve2.fs) !== null && _viteUserConfig$serve3 !== void 0 && _viteUserConfig$serve3.allow ? {
527
+ server: (_viteUserConfig$serve = viteUserConfig.server) !== null && _viteUserConfig$serve !== void 0 && (_viteUserConfig$serve2 = _viteUserConfig$serve.fs) !== null && _viteUserConfig$serve2 !== void 0 && _viteUserConfig$serve2.allow ? {
639
528
  fs: {
640
529
  allow: defaultEntries
641
530
  }
@@ -834,7 +723,7 @@ const reactRouterVitePlugin = _config => {
834
723
  let serverBuildDirectory = getServerBuildDirectory(ctx);
835
724
  let ssrViteManifest = await loadViteManifest(serverBuildDirectory);
836
725
  let clientViteManifest = await loadViteManifest(clientBuildDirectory);
837
- let clientAssetPaths = getViteManifestAssetPaths(clientViteManifest);
726
+ let clientFilePaths = getViteManifestFilePaths(clientViteManifest);
838
727
  let ssrAssetPaths = getViteManifestAssetPaths(ssrViteManifest);
839
728
  // We only move assets that aren't in the client build, otherwise we
840
729
  // remove them. These assets only exist because we explicitly set
@@ -845,7 +734,7 @@ const reactRouterVitePlugin = _config => {
845
734
  let movedAssetPaths = [];
846
735
  for (let ssrAssetPath of ssrAssetPaths) {
847
736
  let src = path__namespace.join(serverBuildDirectory, ssrAssetPath);
848
- if (!clientAssetPaths.has(ssrAssetPath)) {
737
+ if (!clientFilePaths.has(ssrAssetPath)) {
849
738
  let dest = path__namespace.join(clientBuildDirectory, ssrAssetPath);
850
739
  await fse__namespace.move(src, dest);
851
740
  movedAssetPaths.push(dest);
@@ -860,8 +749,19 @@ const reactRouterVitePlugin = _config => {
860
749
  if (movedAssetPaths.length) {
861
750
  viteConfig.logger.info(["", `${colors__default["default"].green("✓")} ${movedAssetPaths.length} asset${movedAssetPaths.length > 1 ? "s" : ""} moved from React Router server build to client assets.`, ...movedAssetPaths.map(movedAssetPath => colors__default["default"].dim(path__namespace.relative(ctx.rootDirectory, movedAssetPath))), ""].join("\n"));
862
751
  }
752
+ if (ctx.reactRouterConfig.prerender != null) {
753
+ // If we have prerender routes, that takes precedence over SPA mode
754
+ // which is ssr:false and only the rot route being rendered
755
+ await handlePrerender(viteConfig, ctx.reactRouterConfig, serverBuildDirectory, clientBuildDirectory);
756
+ } else if (!ctx.reactRouterConfig.ssr) {
757
+ await handleSpaMode(viteConfig, ctx.reactRouterConfig, serverBuildDirectory, clientBuildDirectory);
758
+ }
759
+ // For both SPA mode and prerendering, we can remove the server builds
760
+ // if ssr:false is set
863
761
  if (!ctx.reactRouterConfig.ssr) {
864
- await handleSpaMode(serverBuildDirectory, ctx.reactRouterConfig.serverBuildFile, clientBuildDirectory, viteConfig, ctx.reactRouterConfig.basename);
762
+ // Cleanup - we no longer need the server build assets
763
+ viteConfig.logger.info(["Removing the server build in", colors__default["default"].green(serverBuildDirectory), "due to ssr:false"].join(" "));
764
+ fse__namespace.removeSync(serverBuildDirectory);
865
765
  }
866
766
  }
867
767
  },
@@ -1075,6 +975,13 @@ const reactRouterVitePlugin = _config => {
1075
975
  }
1076
976
  }];
1077
977
  };
978
+ function isInReactRouterMonorepo() {
979
+ // We use '@react-router/server-runtime' for this check since it's a
980
+ // dependency of this package and guaranteed to be in node_modules
981
+ let serverRuntimePath = path__namespace.dirname(require.resolve("@react-router/server-runtime/package.json"));
982
+ let serverRuntimeParentDir = path__namespace.basename(path__namespace.resolve(serverRuntimePath, ".."));
983
+ return serverRuntimeParentDir === "packages";
984
+ }
1078
985
  function isEqualJson(v1, v2) {
1079
986
  return JSON.stringify(v1) === JSON.stringify(v2);
1080
987
  }
@@ -1144,17 +1051,23 @@ async function getRouteMetadata(ctx, viteChildCompiler, route, readRouteFile) {
1144
1051
  };
1145
1052
  return info;
1146
1053
  }
1147
- async function handleSpaMode(serverBuildDirectoryPath, serverBuildFile, clientBuildDirectory, viteConfig, basename) {
1148
- // Create a handler and call it for the `/` path - rendering down to the
1149
- // proper HydrateFallback ... or not! Maybe they have a static landing page
1150
- // generated from routes/_index.tsx.
1151
- let serverBuildPath = path__namespace.join(serverBuildDirectoryPath, serverBuildFile);
1054
+ async function getPrerenderBuildAndHandler(viteConfig, reactRouterConfig, serverBuildDirectory) {
1055
+ let serverBuildPath = path__namespace.join(serverBuildDirectory, reactRouterConfig.serverBuildFile);
1152
1056
  let build = await import(url__namespace.pathToFileURL(serverBuildPath).toString());
1153
1057
  let {
1154
1058
  createRequestHandler: createHandler
1155
1059
  } = await import('@react-router/node');
1156
- let handler = createHandler(build, viteConfig.mode);
1157
- let response = await handler(new Request(`http://localhost${basename}`));
1060
+ return {
1061
+ build,
1062
+ handler: createHandler(build, viteConfig.mode)
1063
+ };
1064
+ }
1065
+ async function handleSpaMode(viteConfig, reactRouterConfig, serverBuildDirectory, clientBuildDirectory) {
1066
+ let {
1067
+ handler
1068
+ } = await getPrerenderBuildAndHandler(viteConfig, reactRouterConfig, serverBuildDirectory);
1069
+ let request = new Request(`http://localhost${reactRouterConfig.basename}`);
1070
+ let response = await handler(request);
1158
1071
  let html = await response.text();
1159
1072
  if (response.status !== 200) {
1160
1073
  throw new Error(`SPA Mode: Received a ${response.status} status code from ` + `\`entry.server.tsx\` while generating the \`index.html\` file.\n${html}`);
@@ -1165,11 +1078,98 @@ async function handleSpaMode(serverBuildDirectoryPath, serverBuildFile, clientBu
1165
1078
  // Write out the index.html file for the SPA
1166
1079
  await fse__namespace.writeFile(path__namespace.join(clientBuildDirectory, "index.html"), html);
1167
1080
  viteConfig.logger.info("SPA Mode: index.html has been written to your " + colors__default["default"].bold(path__namespace.relative(process.cwd(), clientBuildDirectory)) + " directory");
1168
- // Cleanup - we no longer need the server build assets
1169
- fse__namespace.removeSync(serverBuildDirectoryPath);
1081
+ }
1082
+ async function handlePrerender(viteConfig, reactRouterConfig, serverBuildDirectory, clientBuildDirectory) {
1083
+ let {
1084
+ build,
1085
+ handler
1086
+ } = await getPrerenderBuildAndHandler(viteConfig, reactRouterConfig, serverBuildDirectory);
1087
+ let routes = createPrerenderRoutes(build.routes);
1088
+ let routesToPrerender = reactRouterConfig.prerender || ["/"];
1089
+ let requestInit = {
1090
+ headers: {
1091
+ // Header that can be used in the loader to know if you're running at
1092
+ // build time or runtime
1093
+ "X-React-Router-Prerender": "yes"
1094
+ }
1095
+ };
1096
+ for (let path of routesToPrerender) {
1097
+ var _matchRoutes;
1098
+ let hasLoaders = (_matchRoutes = reactRouter.matchRoutes(routes, path)) === null || _matchRoutes === void 0 ? void 0 : _matchRoutes.some(m => m.route.loader);
1099
+ if (hasLoaders) {
1100
+ await prerenderData(handler, reactRouterConfig.basename, path, clientBuildDirectory, viteConfig, requestInit);
1101
+ }
1102
+ await prerenderRoute(handler, reactRouterConfig.basename, path, clientBuildDirectory, viteConfig, requestInit);
1103
+ }
1104
+ async function prerenderData(handler, basename, prerenderPath, clientBuildDirectory, viteConfig, requestInit) {
1105
+ let normalizedPath = `${basename}${prerenderPath === "/" ? "/_root.data" : `${prerenderPath.replace(/\/$/, "")}.data`}`.replace(/\/\/+/g, "/");
1106
+ let request = new Request(`http://localhost${normalizedPath}`, requestInit);
1107
+ let response = await handler(request);
1108
+ let data = await response.text();
1109
+ if (response.status !== 200) {
1110
+ throw new Error(`Prerender: Received a ${response.status} status code from ` + `\`entry.server.tsx\` while prerendering the \`${normalizedPath}\` ` + `path.\n${data}`);
1111
+ }
1112
+ // Write out the .data file
1113
+ let outdir = path__namespace.relative(process.cwd(), clientBuildDirectory);
1114
+ let outfile = path__namespace.join(outdir, normalizedPath.split("/").join(path__namespace.sep));
1115
+ await fse__namespace.ensureDir(path__namespace.dirname(outfile));
1116
+ await fse__namespace.outputFile(outfile, data);
1117
+ viteConfig.logger.info(`Prerender: Generated ${colors__default["default"].bold(outfile)}`);
1118
+ }
1119
+ }
1120
+ async function prerenderRoute(handler, basename, prerenderPath, clientBuildDirectory, viteConfig, requestInit) {
1121
+ let normalizedPath = `${basename}${prerenderPath}/`.replace(/\/\/+/g, "/");
1122
+ let request = new Request(`http://localhost${normalizedPath}`, requestInit);
1123
+ let response = await handler(request);
1124
+ let html = await response.text();
1125
+ if (response.status !== 200) {
1126
+ throw new Error(`Prerender: Received a ${response.status} status code from ` + `\`entry.server.tsx\` while prerendering the \`${normalizedPath}\` ` + `path.\n${html}`);
1127
+ }
1128
+ if (!html.includes("window.__remixContext =") || !html.includes("window.__remixRouteModules =")) {
1129
+ throw new Error("Prerender: Did you forget to include <Scripts/> in your `root.tsx` " + "`HydrateFallback` component? Your prerendered HTML files cannot " + "hydrate into a SPA without `<Scripts />`.");
1130
+ }
1131
+ // Write out the HTML file
1132
+ let outdir = path__namespace.relative(process.cwd(), clientBuildDirectory);
1133
+ let outfile = path__namespace.join(outdir, ...normalizedPath.split("/"), "index.html");
1134
+ await fse__namespace.ensureDir(path__namespace.dirname(outfile));
1135
+ await fse__namespace.outputFile(outfile, html);
1136
+ viteConfig.logger.info(`Prerender: Generated ${colors__default["default"].bold(outfile)}`);
1137
+ }
1138
+ // Note: Duplicated from remix-server-runtime
1139
+ function groupRoutesByParentId(manifest) {
1140
+ let routes = {};
1141
+ Object.values(manifest).forEach(route => {
1142
+ let parentId = route.parentId || "";
1143
+ if (!routes[parentId]) {
1144
+ routes[parentId] = [];
1145
+ }
1146
+ routes[parentId].push(route);
1147
+ });
1148
+ return routes;
1149
+ }
1150
+ // Note: Duplicated from remix-server-runtime
1151
+ function createPrerenderRoutes(manifest, parentId = "", routesByParentId = groupRoutesByParentId(manifest)) {
1152
+ return (routesByParentId[parentId] || []).map(route => {
1153
+ let commonRoute = {
1154
+ // Always include root due to default boundaries
1155
+ hasErrorBoundary: route.id === "root" || route.module.ErrorBoundary != null,
1156
+ id: route.id,
1157
+ path: route.path,
1158
+ loader: route.module.loader ? () => null : undefined,
1159
+ action: undefined,
1160
+ handle: route.module.handle
1161
+ };
1162
+ return route.index ? {
1163
+ index: true,
1164
+ ...commonRoute
1165
+ } : {
1166
+ caseSensitive: route.caseSensitive,
1167
+ children: createPrerenderRoutes(manifest, route.id, routesByParentId),
1168
+ ...commonRoute
1169
+ };
1170
+ });
1170
1171
  }
1171
1172
 
1172
- exports.configRouteToBranchRoute = configRouteToBranchRoute;
1173
1173
  exports.extractPluginContext = extractPluginContext;
1174
1174
  exports.getServerBuildDirectory = getServerBuildDirectory;
1175
1175
  exports.loadPluginContext = loadPluginContext;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @react-router/dev v0.0.0-experimental-7b411a741
2
+ * @react-router/dev v0.0.0-experimental-4ed3f5da9
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-7b411a741
2
+ * @react-router/dev v0.0.0-experimental-4ed3f5da9
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-7b411a741
2
+ * @react-router/dev v0.0.0-experimental-4ed3f5da9
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1,11 +1,11 @@
1
1
  import type { ServerBuild } from "@react-router/server-runtime";
2
2
  import type { ViteDevServer } from "vite";
3
- import type { RemixConfig as ResolvedRemixConfig } from "../config";
3
+ import type { ResolvedVitePluginConfig } from "../config";
4
4
  export declare const isCssModulesFile: (file: string) => boolean;
5
5
  export declare const getStylesForUrl: ({ viteDevServer, rootDirectory, reactRouterConfig, entryClientFilePath, cssModulesManifest, build, url, }: {
6
6
  viteDevServer: ViteDevServer;
7
7
  rootDirectory: string;
8
- reactRouterConfig: Pick<ResolvedRemixConfig, "appDirectory" | "routes">;
8
+ reactRouterConfig: Pick<ResolvedVitePluginConfig, "appDirectory" | "routes">;
9
9
  entryClientFilePath: string;
10
10
  cssModulesManifest: Record<string, string>;
11
11
  build: ServerBuild;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @react-router/dev v0.0.0-experimental-7b411a741
2
+ * @react-router/dev v0.0.0-experimental-4ed3f5da9
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
package/dist/vite/vmod.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @react-router/dev v0.0.0-experimental-7b411a741
2
+ * @react-router/dev v0.0.0-experimental-4ed3f5da9
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@react-router/dev",
3
- "version": "0.0.0-experimental-7b411a741",
3
+ "version": "0.0.0-experimental-4ed3f5da9",
4
4
  "description": "Dev tools and CLI for React Router",
5
5
  "homepage": "https://reactrouter.com",
6
6
  "bugs": {
@@ -42,9 +42,9 @@
42
42
  "react-refresh": "^0.14.0",
43
43
  "semver": "^7.3.7",
44
44
  "set-cookie-parser": "^2.6.0",
45
- "react-router": "0.0.0-experimental-7b411a741",
46
- "@react-router/server-runtime": "0.0.0-experimental-7b411a741",
47
- "@react-router/node": "0.0.0-experimental-7b411a741"
45
+ "@react-router/node": "0.0.0-experimental-4ed3f5da9",
46
+ "@react-router/server-runtime": "0.0.0-experimental-4ed3f5da9",
47
+ "react-router": "0.0.0-experimental-4ed3f5da9"
48
48
  },
49
49
  "devDependencies": {
50
50
  "@types/babel__core": "^7.20.5",
@@ -69,14 +69,14 @@
69
69
  "tiny-invariant": "^1.2.0",
70
70
  "vite": "^5.1.0",
71
71
  "wrangler": "^3.28.2",
72
- "@react-router/serve": "0.0.0-experimental-7b411a741"
72
+ "@react-router/serve": "0.0.0-experimental-4ed3f5da9"
73
73
  },
74
74
  "peerDependencies": {
75
75
  "typescript": "^5.1.0",
76
76
  "vite": "^5.1.0",
77
77
  "wrangler": "^3.28.2",
78
- "@react-router/serve": "^0.0.0-experimental-7b411a741",
79
- "react-router": "^0.0.0-experimental-7b411a741"
78
+ "@react-router/serve": "^0.0.0-experimental-4ed3f5da9",
79
+ "react-router": "^0.0.0-experimental-4ed3f5da9"
80
80
  },
81
81
  "peerDependenciesMeta": {
82
82
  "@react-router/serve": {
@@ -1,28 +0,0 @@
1
- /**
2
- * @react-router/dev v0.0.0-experimental-7b411a741
3
- *
4
- * Copyright (c) Remix Software Inc.
5
- *
6
- * This source code is licensed under the MIT license found in the
7
- * LICENSE.md file in the root directory of this source tree.
8
- *
9
- * @license MIT
10
- */
11
- 'use strict';
12
-
13
- Object.defineProperty(exports, '__esModule', { value: true });
14
-
15
- /**
16
- * The mode to use when running the server.
17
- */
18
- exports.ServerMode = void 0;
19
- (function (ServerMode) {
20
- ServerMode["Development"] = "development";
21
- ServerMode["Production"] = "production";
22
- ServerMode["Test"] = "test";
23
- })(exports.ServerMode || (exports.ServerMode = {}));
24
- function isValidServerMode(mode) {
25
- return mode === exports.ServerMode.Development || mode === exports.ServerMode.Production || mode === exports.ServerMode.Test;
26
- }
27
-
28
- exports.isValidServerMode = isValidServerMode;