@react-router/dev 0.0.0-experimental-902325fda → 0.0.0-experimental-004e483a8
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 +367 -164
- package/dist/config.d.ts +4 -0
- package/dist/config.js +1 -1
- package/dist/routes.js +1 -1
- package/dist/static/refresh-utils.cjs +1 -1
- package/dist/vite/cloudflare.js +487 -3
- package/dist/vite.js +374 -263
- package/package.json +6 -6
package/dist/vite.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @react-router/dev v0.0.0-experimental-
|
|
2
|
+
* @react-router/dev v0.0.0-experimental-004e483a8
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -59,6 +59,7 @@ var import_kebabCase = __toESM(require("lodash/kebabCase"));
|
|
|
59
59
|
|
|
60
60
|
// typegen/index.ts
|
|
61
61
|
var import_node_fs2 = __toESM(require("fs"));
|
|
62
|
+
var import_dedent2 = __toESM(require("dedent"));
|
|
62
63
|
var Path4 = __toESM(require("pathe"));
|
|
63
64
|
var import_picocolors2 = __toESM(require("picocolors"));
|
|
64
65
|
|
|
@@ -453,7 +454,8 @@ async function resolveConfig({
|
|
|
453
454
|
}
|
|
454
455
|
let future = {
|
|
455
456
|
unstable_optimizeDeps: reactRouterUserConfig.future?.unstable_optimizeDeps ?? false,
|
|
456
|
-
unstable_splitRouteModules: reactRouterUserConfig.future?.unstable_splitRouteModules ?? false
|
|
457
|
+
unstable_splitRouteModules: reactRouterUserConfig.future?.unstable_splitRouteModules ?? false,
|
|
458
|
+
unstable_viteEnvironmentApi: reactRouterUserConfig.future?.unstable_viteEnvironmentApi ?? false
|
|
457
459
|
};
|
|
458
460
|
let reactRouterConfig = deepFreeze({
|
|
459
461
|
appDirectory,
|
|
@@ -632,6 +634,19 @@ function findEntry(dir, basename2, options) {
|
|
|
632
634
|
return void 0;
|
|
633
635
|
}
|
|
634
636
|
|
|
637
|
+
// vite/babel.ts
|
|
638
|
+
var babel_exports = {};
|
|
639
|
+
__export(babel_exports, {
|
|
640
|
+
generate: () => generate,
|
|
641
|
+
parse: () => import_parser.parse,
|
|
642
|
+
t: () => t,
|
|
643
|
+
traverse: () => traverse
|
|
644
|
+
});
|
|
645
|
+
var import_parser = require("@babel/parser");
|
|
646
|
+
var t = __toESM(require("@babel/types"));
|
|
647
|
+
var traverse = require("@babel/traverse").default;
|
|
648
|
+
var generate = require("@babel/generator").default;
|
|
649
|
+
|
|
635
650
|
// typegen/generate.ts
|
|
636
651
|
var import_dedent = __toESM(require("dedent"));
|
|
637
652
|
var Path3 = __toESM(require("pathe"));
|
|
@@ -653,7 +668,7 @@ function getTypesPath(ctx, route) {
|
|
|
653
668
|
}
|
|
654
669
|
|
|
655
670
|
// typegen/generate.ts
|
|
656
|
-
function
|
|
671
|
+
function generate2(ctx, route) {
|
|
657
672
|
const lineage = getRouteLineage(ctx.config.routes, route);
|
|
658
673
|
const urlpath = lineage.map((route2) => route2.path).join("/");
|
|
659
674
|
const typesPath = getTypesPath(ctx, route);
|
|
@@ -799,17 +814,77 @@ async function writeAll(ctx) {
|
|
|
799
814
|
import_node_fs2.default.rmSync(typegenDir, { recursive: true, force: true });
|
|
800
815
|
Object.values(ctx.config.routes).forEach((route) => {
|
|
801
816
|
const typesPath = getTypesPath(ctx, route);
|
|
802
|
-
const content =
|
|
817
|
+
const content = generate2(ctx, route);
|
|
803
818
|
import_node_fs2.default.mkdirSync(Path4.dirname(typesPath), { recursive: true });
|
|
804
819
|
import_node_fs2.default.writeFileSync(typesPath, content);
|
|
805
820
|
});
|
|
821
|
+
const registerPath = Path4.join(typegenDir, "+register.ts");
|
|
822
|
+
import_node_fs2.default.writeFileSync(registerPath, register(ctx));
|
|
806
823
|
}
|
|
824
|
+
function register(ctx) {
|
|
825
|
+
const register2 = import_dedent2.default`
|
|
826
|
+
import "react-router";
|
|
807
827
|
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
828
|
+
declare module "react-router" {
|
|
829
|
+
interface Register {
|
|
830
|
+
params: Params;
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
`;
|
|
834
|
+
const { t: t2 } = babel_exports;
|
|
835
|
+
const typeParams = t2.tsTypeAliasDeclaration(
|
|
836
|
+
t2.identifier("Params"),
|
|
837
|
+
null,
|
|
838
|
+
t2.tsTypeLiteral(
|
|
839
|
+
Object.values(ctx.config.routes).map((route) => {
|
|
840
|
+
const lineage = getRouteLineage2(ctx.config.routes, route);
|
|
841
|
+
const fullpath = lineage.map((route2) => route2.path).join("/");
|
|
842
|
+
const params = parseParams2(fullpath);
|
|
843
|
+
return t2.tsPropertySignature(
|
|
844
|
+
t2.stringLiteral(fullpath),
|
|
845
|
+
t2.tsTypeAnnotation(
|
|
846
|
+
t2.tsTypeLiteral(
|
|
847
|
+
Object.entries(params).map(([param, isRequired]) => {
|
|
848
|
+
const property = t2.tsPropertySignature(
|
|
849
|
+
t2.stringLiteral(param),
|
|
850
|
+
t2.tsTypeAnnotation(t2.tsStringKeyword())
|
|
851
|
+
);
|
|
852
|
+
property.optional = !isRequired;
|
|
853
|
+
return property;
|
|
854
|
+
})
|
|
855
|
+
)
|
|
856
|
+
)
|
|
857
|
+
);
|
|
858
|
+
})
|
|
859
|
+
)
|
|
860
|
+
);
|
|
861
|
+
return [register2, generate(typeParams).code].join("\n\n");
|
|
862
|
+
}
|
|
863
|
+
function parseParams2(fullpath) {
|
|
864
|
+
const result = {};
|
|
865
|
+
let segments = fullpath.split("/");
|
|
866
|
+
segments.forEach((segment) => {
|
|
867
|
+
const match = segment.match(/^:([\w-]+)(\?)?/);
|
|
868
|
+
if (!match) return;
|
|
869
|
+
const param = match[1];
|
|
870
|
+
const isRequired = match[2] === void 0;
|
|
871
|
+
result[param] ||= isRequired;
|
|
872
|
+
return;
|
|
873
|
+
});
|
|
874
|
+
const hasSplat = segments.at(-1) === "*";
|
|
875
|
+
if (hasSplat) result["*"] = true;
|
|
876
|
+
return result;
|
|
877
|
+
}
|
|
878
|
+
function getRouteLineage2(routes, route) {
|
|
879
|
+
const result = [];
|
|
880
|
+
while (route) {
|
|
881
|
+
result.push(route);
|
|
882
|
+
if (!route.parentId) break;
|
|
883
|
+
route = routes[route.parentId];
|
|
884
|
+
}
|
|
885
|
+
result.reverse();
|
|
886
|
+
return result;
|
|
887
|
+
}
|
|
813
888
|
|
|
814
889
|
// vite/node-adapter.ts
|
|
815
890
|
var import_node_events = require("events");
|
|
@@ -1597,7 +1672,7 @@ function getChunkedExport(code, exportName, generateOptions = {}, cache, cacheKe
|
|
|
1597
1672
|
}
|
|
1598
1673
|
throw new Error(`Unknown export node type: ${node.type}`);
|
|
1599
1674
|
}).filter((node) => node !== null);
|
|
1600
|
-
return
|
|
1675
|
+
return generate(ast, generateOptions);
|
|
1601
1676
|
}
|
|
1602
1677
|
);
|
|
1603
1678
|
}
|
|
@@ -1713,7 +1788,7 @@ function omitChunkedExports(code, exportNames, generateOptions = {}, cache, cach
|
|
|
1713
1788
|
if (ast.program.body.length === 0) {
|
|
1714
1789
|
return void 0;
|
|
1715
1790
|
}
|
|
1716
|
-
return
|
|
1791
|
+
return generate(ast, generateOptions);
|
|
1717
1792
|
}
|
|
1718
1793
|
);
|
|
1719
1794
|
}
|
|
@@ -1775,7 +1850,7 @@ function getRouteChunkNameFromModuleId(id) {
|
|
|
1775
1850
|
}
|
|
1776
1851
|
|
|
1777
1852
|
// vite/with-props.ts
|
|
1778
|
-
var
|
|
1853
|
+
var import_dedent3 = __toESM(require("dedent"));
|
|
1779
1854
|
var vmod = create("with-props");
|
|
1780
1855
|
var NAMED_COMPONENT_EXPORTS = ["HydrateFallback", "ErrorBoundary"];
|
|
1781
1856
|
var plugin = {
|
|
@@ -1786,7 +1861,7 @@ var plugin = {
|
|
|
1786
1861
|
},
|
|
1787
1862
|
async load(id) {
|
|
1788
1863
|
if (id !== vmod.resolvedId) return;
|
|
1789
|
-
return
|
|
1864
|
+
return import_dedent3.default`
|
|
1790
1865
|
import { createElement as h } from "react";
|
|
1791
1866
|
import { useActionData, useLoaderData, useMatches, useParams, useRouteError } from "react-router";
|
|
1792
1867
|
|
|
@@ -1806,8 +1881,6 @@ var plugin = {
|
|
|
1806
1881
|
return function Wrapped() {
|
|
1807
1882
|
const props = {
|
|
1808
1883
|
params: useParams(),
|
|
1809
|
-
loaderData: useLoaderData(),
|
|
1810
|
-
actionData: useActionData(),
|
|
1811
1884
|
};
|
|
1812
1885
|
return h(HydrateFallback, props);
|
|
1813
1886
|
};
|
|
@@ -1915,6 +1988,20 @@ var CLIENT_ROUTE_EXPORTS = [
|
|
|
1915
1988
|
"shouldRevalidate"
|
|
1916
1989
|
];
|
|
1917
1990
|
var BUILD_CLIENT_ROUTE_QUERY_STRING = "?__react-router-build-client-route";
|
|
1991
|
+
var SSR_BUNDLE_PREFIX = "ssrBundle_";
|
|
1992
|
+
function isSeverBundleEnvironmentName(name) {
|
|
1993
|
+
return name.startsWith(SSR_BUNDLE_PREFIX);
|
|
1994
|
+
}
|
|
1995
|
+
function getServerEnvironmentEntries(record, buildManifest) {
|
|
1996
|
+
return Object.entries(record).filter(
|
|
1997
|
+
([name]) => buildManifest.serverBundles ? isSeverBundleEnvironmentName(name) : name === "ssr"
|
|
1998
|
+
);
|
|
1999
|
+
}
|
|
2000
|
+
function getServerEnvironmentValues(record, buildManifest) {
|
|
2001
|
+
return getServerEnvironmentEntries(record, buildManifest).map(
|
|
2002
|
+
([, value]) => value
|
|
2003
|
+
);
|
|
2004
|
+
}
|
|
1918
2005
|
var isRouteEntryModuleId = (id) => {
|
|
1919
2006
|
return id.endsWith(BUILD_CLIENT_ROUTE_QUERY_STRING);
|
|
1920
2007
|
};
|
|
@@ -2083,7 +2170,7 @@ var resolveEnvironmentBuildContext = ({
|
|
|
2083
2170
|
let buildContext = viteUserConfig.__reactRouterEnvironmentBuildContext;
|
|
2084
2171
|
let resolvedBuildContext = {
|
|
2085
2172
|
name: buildContext.name,
|
|
2086
|
-
options: buildContext.resolveOptions({
|
|
2173
|
+
options: buildContext.resolveOptions({ viteUserConfig })
|
|
2087
2174
|
};
|
|
2088
2175
|
return resolvedBuildContext;
|
|
2089
2176
|
};
|
|
@@ -2108,6 +2195,7 @@ var reactRouterVitePlugin = () => {
|
|
|
2108
2195
|
let viteUserConfig;
|
|
2109
2196
|
let viteConfigEnv;
|
|
2110
2197
|
let viteConfig;
|
|
2198
|
+
let buildManifest;
|
|
2111
2199
|
let cssModulesManifest = {};
|
|
2112
2200
|
let viteChildCompiler = null;
|
|
2113
2201
|
let cache = /* @__PURE__ */ new Map();
|
|
@@ -2168,11 +2256,6 @@ var reactRouterVitePlugin = () => {
|
|
|
2168
2256
|
// Otherwise, all routes are imported as usual
|
|
2169
2257
|
ctx.reactRouterConfig.routes
|
|
2170
2258
|
);
|
|
2171
|
-
let prerenderPaths = await getPrerenderPaths(
|
|
2172
|
-
ctx.reactRouterConfig.prerender,
|
|
2173
|
-
ctx.reactRouterConfig.ssr,
|
|
2174
|
-
routes
|
|
2175
|
-
);
|
|
2176
2259
|
return `
|
|
2177
2260
|
import * as entryServer from ${JSON.stringify(
|
|
2178
2261
|
resolveFileUrl(ctx, ctx.entryServerFilePath)
|
|
@@ -2199,7 +2282,6 @@ var reactRouterVitePlugin = () => {
|
|
|
2199
2282
|
export const future = ${JSON.stringify(ctx.reactRouterConfig.future)};
|
|
2200
2283
|
export const ssr = ${ctx.reactRouterConfig.ssr};
|
|
2201
2284
|
export const isSpaMode = ${isSpaModeEnabled(ctx.reactRouterConfig)};
|
|
2202
|
-
export const prerender = ${JSON.stringify(prerenderPaths)};
|
|
2203
2285
|
export const publicPath = ${JSON.stringify(ctx.publicPath)};
|
|
2204
2286
|
export const entry = { module: entryServer };
|
|
2205
2287
|
export const routes = {
|
|
@@ -2432,14 +2514,6 @@ var reactRouterVitePlugin = () => {
|
|
|
2432
2514
|
let viteClientConditions = [
|
|
2433
2515
|
...vite2.defaultClientConditions ?? []
|
|
2434
2516
|
];
|
|
2435
|
-
let packageRoot = path6.dirname(
|
|
2436
|
-
require.resolve("@react-router/dev/package.json")
|
|
2437
|
-
);
|
|
2438
|
-
let { moduleSyncEnabled } = await import(`file:///${path6.join(packageRoot, "module-sync-enabled/index.mjs")}`);
|
|
2439
|
-
let viteServerConditions = [
|
|
2440
|
-
...vite2.defaultServerConditions ?? [],
|
|
2441
|
-
...moduleSyncEnabled ? ["module-sync"] : []
|
|
2442
|
-
];
|
|
2443
2517
|
logger = vite2.createLogger(viteUserConfig.logLevel, {
|
|
2444
2518
|
prefix: "[react-router]"
|
|
2445
2519
|
});
|
|
@@ -2455,26 +2529,37 @@ var reactRouterVitePlugin = () => {
|
|
|
2455
2529
|
watch: viteCommand === "serve"
|
|
2456
2530
|
});
|
|
2457
2531
|
await updatePluginContext();
|
|
2532
|
+
buildManifest = await getBuildManifest(ctx);
|
|
2458
2533
|
Object.assign(
|
|
2459
2534
|
process.env,
|
|
2460
2535
|
vite2.loadEnv(
|
|
2461
2536
|
viteConfigEnv.mode,
|
|
2462
|
-
ctx.rootDirectory,
|
|
2537
|
+
viteUserConfig.envDir ?? ctx.rootDirectory,
|
|
2463
2538
|
// We override default prefix of "VITE_" with a blank string since
|
|
2464
2539
|
// we're targeting the server, so we want to load all environment
|
|
2465
2540
|
// variables, not just those explicitly marked for the client
|
|
2466
2541
|
""
|
|
2467
2542
|
)
|
|
2468
2543
|
);
|
|
2544
|
+
let environments = await getEnvironmentsOptions(
|
|
2545
|
+
ctx,
|
|
2546
|
+
buildManifest,
|
|
2547
|
+
viteCommand,
|
|
2548
|
+
{ viteUserConfig }
|
|
2549
|
+
);
|
|
2550
|
+
let serverEnvironment = getServerEnvironmentValues(
|
|
2551
|
+
environments,
|
|
2552
|
+
buildManifest
|
|
2553
|
+
)[0];
|
|
2554
|
+
invariant(serverEnvironment);
|
|
2555
|
+
let clientEnvironment = environments.client;
|
|
2556
|
+
invariant(clientEnvironment);
|
|
2469
2557
|
return {
|
|
2470
2558
|
__reactRouterPluginContext: ctx,
|
|
2471
2559
|
appType: viteCommand === "serve" && viteConfigEnv.mode === "production" && ctx.reactRouterConfig.ssr === false ? "spa" : "custom",
|
|
2472
2560
|
ssr: {
|
|
2473
|
-
external:
|
|
2474
|
-
resolve:
|
|
2475
|
-
conditions: viteCommand === "build" ? viteServerConditions : ["development", ...viteServerConditions],
|
|
2476
|
-
externalConditions: viteCommand === "build" ? viteServerConditions : ["development", ...viteServerConditions]
|
|
2477
|
-
}
|
|
2561
|
+
external: serverEnvironment.resolve?.external,
|
|
2562
|
+
resolve: serverEnvironment.resolve
|
|
2478
2563
|
},
|
|
2479
2564
|
optimizeDeps: {
|
|
2480
2565
|
entries: ctx.reactRouterConfig.future.unstable_optimizeDeps ? [
|
|
@@ -2523,11 +2608,41 @@ var reactRouterVitePlugin = () => {
|
|
|
2523
2608
|
// will throw an error that the file is not allowed to be read.
|
|
2524
2609
|
// https://vitejs.dev/config/server-options#server-fs-allow
|
|
2525
2610
|
server: viteUserConfig.server?.fs?.allow ? { fs: { allow: defaultEntries } } : void 0,
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2611
|
+
...ctx.reactRouterConfig.future.unstable_viteEnvironmentApi ? {
|
|
2612
|
+
environments,
|
|
2613
|
+
build: {
|
|
2614
|
+
// This isn't honored by the SSR environment config (which seems
|
|
2615
|
+
// to be a Vite bug?) so we set it here too.
|
|
2616
|
+
ssrEmitAssets: true
|
|
2617
|
+
},
|
|
2618
|
+
builder: {
|
|
2619
|
+
sharedConfigBuild: true,
|
|
2620
|
+
sharedPlugins: true,
|
|
2621
|
+
async buildApp(builder) {
|
|
2622
|
+
invariant(viteConfig);
|
|
2623
|
+
invariant(buildManifest);
|
|
2624
|
+
viteConfig.logger.info(
|
|
2625
|
+
"Using Vite Environment API (experimental)"
|
|
2626
|
+
);
|
|
2627
|
+
let { reactRouterConfig } = ctx;
|
|
2628
|
+
await cleanBuildDirectory(viteConfig, ctx);
|
|
2629
|
+
await builder.build(builder.environments.client);
|
|
2630
|
+
let serverEnvironments = getServerEnvironmentValues(
|
|
2631
|
+
builder.environments,
|
|
2632
|
+
buildManifest
|
|
2633
|
+
);
|
|
2634
|
+
await Promise.all(serverEnvironments.map(builder.build));
|
|
2635
|
+
await cleanViteManifests(environments, ctx);
|
|
2636
|
+
await reactRouterConfig.buildEnd?.({
|
|
2637
|
+
buildManifest,
|
|
2638
|
+
reactRouterConfig,
|
|
2639
|
+
viteConfig
|
|
2640
|
+
});
|
|
2641
|
+
}
|
|
2642
|
+
}
|
|
2643
|
+
} : {
|
|
2644
|
+
build: ctx.environmentBuildContext?.options.build ?? (viteConfigEnv.isSsrBuild ? serverEnvironment.build : clientEnvironment.build)
|
|
2645
|
+
}
|
|
2531
2646
|
};
|
|
2532
2647
|
},
|
|
2533
2648
|
async configResolved(resolvedViteConfig) {
|
|
@@ -2685,14 +2800,15 @@ var reactRouterVitePlugin = () => {
|
|
|
2685
2800
|
// After the SSR build is finished, we inspect the Vite manifest for
|
|
2686
2801
|
// the SSR build and move server-only assets to client assets directory
|
|
2687
2802
|
async handler() {
|
|
2688
|
-
|
|
2803
|
+
let { future } = ctx.reactRouterConfig;
|
|
2804
|
+
if (future.unstable_viteEnvironmentApi ? this.environment.name === "client" : !viteConfigEnv.isSsrBuild) {
|
|
2689
2805
|
return;
|
|
2690
2806
|
}
|
|
2691
2807
|
invariant(viteConfig);
|
|
2692
2808
|
let clientBuildDirectory = getClientBuildDirectory(
|
|
2693
2809
|
ctx.reactRouterConfig
|
|
2694
2810
|
);
|
|
2695
|
-
let serverBuildDirectory = ctx.environmentBuildContext?.options.build
|
|
2811
|
+
let serverBuildDirectory = future.unstable_viteEnvironmentApi ? this.environment.config?.build?.outDir : ctx.environmentBuildContext?.options.build?.outDir ?? getServerBuildDirectory(ctx);
|
|
2696
2812
|
let ssrViteManifest = await loadViteManifest(serverBuildDirectory);
|
|
2697
2813
|
let ssrAssetPaths = getViteManifestAssetPaths(ssrViteManifest);
|
|
2698
2814
|
let movedAssetPaths = [];
|
|
@@ -2726,7 +2842,7 @@ var reactRouterVitePlugin = () => {
|
|
|
2726
2842
|
].join("\n")
|
|
2727
2843
|
);
|
|
2728
2844
|
}
|
|
2729
|
-
if (
|
|
2845
|
+
if (ctx.reactRouterConfig.prerender != null && ctx.reactRouterConfig.prerender !== false) {
|
|
2730
2846
|
await handlePrerender(
|
|
2731
2847
|
viteConfig,
|
|
2732
2848
|
ctx.reactRouterConfig,
|
|
@@ -3000,15 +3116,12 @@ var reactRouterVitePlugin = () => {
|
|
|
3000
3116
|
if (!route) return;
|
|
3001
3117
|
if (!options?.ssr && isSpaModeEnabled(ctx.reactRouterConfig)) {
|
|
3002
3118
|
let exportNames = getExportNames(code);
|
|
3003
|
-
let serverOnlyExports = exportNames.filter(
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
}
|
|
3007
|
-
return SERVER_ONLY_ROUTE_EXPORTS.includes(exp);
|
|
3008
|
-
});
|
|
3119
|
+
let serverOnlyExports = exportNames.filter(
|
|
3120
|
+
(exp) => SERVER_ONLY_ROUTE_EXPORTS.includes(exp)
|
|
3121
|
+
);
|
|
3009
3122
|
if (serverOnlyExports.length > 0) {
|
|
3010
3123
|
let str = serverOnlyExports.map((e) => `\`${e}\``).join(", ");
|
|
3011
|
-
let message = `SPA Mode: ${serverOnlyExports.length} invalid route export(s) in \`${route.file}\`: ${str}. See https://
|
|
3124
|
+
let message = `SPA Mode: ${serverOnlyExports.length} invalid route export(s) in \`${route.file}\`: ${str}. See https://remix.run/guides/spa-mode for more information.`;
|
|
3012
3125
|
throw Error(message);
|
|
3013
3126
|
}
|
|
3014
3127
|
if (route.id !== "root") {
|
|
@@ -3016,7 +3129,7 @@ var reactRouterVitePlugin = () => {
|
|
|
3016
3129
|
(exp) => exp === "HydrateFallback"
|
|
3017
3130
|
);
|
|
3018
3131
|
if (hasHydrateFallback) {
|
|
3019
|
-
let message = `SPA Mode: Invalid \`HydrateFallback\` export found in \`${route.file}\`. \`HydrateFallback\` is only permitted on the root route in SPA Mode. See https://
|
|
3132
|
+
let message = `SPA Mode: Invalid \`HydrateFallback\` export found in \`${route.file}\`. \`HydrateFallback\` is only permitted on the root route in SPA Mode. See https://remix.run/guides/spa-mode for more information.`;
|
|
3020
3133
|
throw Error(message);
|
|
3021
3134
|
}
|
|
3022
3135
|
}
|
|
@@ -3027,7 +3140,7 @@ var reactRouterVitePlugin = () => {
|
|
|
3027
3140
|
removeExports(ast, SERVER_ONLY_ROUTE_EXPORTS);
|
|
3028
3141
|
}
|
|
3029
3142
|
transform(ast);
|
|
3030
|
-
return
|
|
3143
|
+
return generate(ast, {
|
|
3031
3144
|
sourceMaps: true,
|
|
3032
3145
|
filename: id,
|
|
3033
3146
|
sourceFileName: filepath
|
|
@@ -3309,11 +3422,8 @@ async function getRouteMetadata(cache, ctx, viteChildCompiler, route, readRouteF
|
|
|
3309
3422
|
};
|
|
3310
3423
|
return info;
|
|
3311
3424
|
}
|
|
3312
|
-
function isPrerenderingEnabled(reactRouterConfig) {
|
|
3313
|
-
return reactRouterConfig.prerender != null && reactRouterConfig.prerender !== false;
|
|
3314
|
-
}
|
|
3315
3425
|
function isSpaModeEnabled(reactRouterConfig) {
|
|
3316
|
-
return reactRouterConfig.ssr === false &&
|
|
3426
|
+
return reactRouterConfig.ssr === false && (reactRouterConfig.prerender == null || reactRouterConfig.prerender === false || Array.isArray(reactRouterConfig.prerender) && reactRouterConfig.prerender.length === 1 && reactRouterConfig.prerender[0] === "/");
|
|
3317
3427
|
}
|
|
3318
3428
|
async function getPrerenderBuildAndHandler(viteConfig, serverBuildDirectory, serverBuildFile) {
|
|
3319
3429
|
let serverBuildPath = path6.join(serverBuildDirectory, serverBuildFile);
|
|
@@ -3325,49 +3435,20 @@ async function getPrerenderBuildAndHandler(viteConfig, serverBuildDirectory, ser
|
|
|
3325
3435
|
};
|
|
3326
3436
|
}
|
|
3327
3437
|
async function handleSpaMode(viteConfig, reactRouterConfig, serverBuildDirectory, serverBuildFile, clientBuildDirectory) {
|
|
3328
|
-
let {
|
|
3438
|
+
let { handler } = await getPrerenderBuildAndHandler(
|
|
3329
3439
|
viteConfig,
|
|
3330
3440
|
serverBuildDirectory,
|
|
3331
3441
|
serverBuildFile
|
|
3332
3442
|
);
|
|
3333
|
-
let request = new Request(`http://localhost${reactRouterConfig.basename}
|
|
3334
|
-
headers: {
|
|
3335
|
-
// Enable SPA mode in the server runtime and only render down to the root
|
|
3336
|
-
"X-React-Router-SPA-Mode": "yes"
|
|
3337
|
-
}
|
|
3338
|
-
});
|
|
3443
|
+
let request = new Request(`http://localhost${reactRouterConfig.basename}`);
|
|
3339
3444
|
let response = await handler(request);
|
|
3340
3445
|
let html = await response.text();
|
|
3341
|
-
|
|
3342
|
-
|
|
3343
|
-
|
|
3344
|
-
|
|
3345
|
-
|
|
3346
|
-
|
|
3347
|
-
` + html
|
|
3348
|
-
);
|
|
3349
|
-
} else {
|
|
3350
|
-
throw new Error(
|
|
3351
|
-
`SPA Mode: Received a ${response.status} status code from \`entry.server.tsx\` while prerendering your \`${filename3}\` file.
|
|
3352
|
-
` + html
|
|
3353
|
-
);
|
|
3354
|
-
}
|
|
3355
|
-
}
|
|
3356
|
-
if (!html.includes("window.__reactRouterContext =") || !html.includes("window.__reactRouterRouteModules =")) {
|
|
3357
|
-
throw new Error(
|
|
3358
|
-
"SPA Mode: Did you forget to include `<Scripts/>` in your root route? Your pre-rendered HTML cannot hydrate without `<Scripts />`."
|
|
3359
|
-
);
|
|
3360
|
-
}
|
|
3361
|
-
await fse.writeFile(path6.join(clientBuildDirectory, filename3), html);
|
|
3362
|
-
let prettyDir = path6.relative(process.cwd(), clientBuildDirectory);
|
|
3363
|
-
let prettyPath = path6.join(prettyDir, filename3);
|
|
3364
|
-
if (build.prerender.length > 0) {
|
|
3365
|
-
viteConfig.logger.info(
|
|
3366
|
-
`Prerender (html): SPA Fallback -> ${import_picocolors3.default.bold(prettyPath)}`
|
|
3367
|
-
);
|
|
3368
|
-
} else {
|
|
3369
|
-
viteConfig.logger.info(`SPA Mode: Generated ${import_picocolors3.default.bold(prettyPath)}`);
|
|
3370
|
-
}
|
|
3446
|
+
validatePrerenderedResponse(response, html, "SPA Mode", "/");
|
|
3447
|
+
validatePrerenderedHtml(html, "SPA Mode");
|
|
3448
|
+
await fse.writeFile(path6.join(clientBuildDirectory, "index.html"), html);
|
|
3449
|
+
viteConfig.logger.info(
|
|
3450
|
+
"SPA Mode: index.html has been written to your " + import_picocolors3.default.bold(path6.relative(process.cwd(), clientBuildDirectory)) + " directory"
|
|
3451
|
+
);
|
|
3371
3452
|
}
|
|
3372
3453
|
async function handlePrerender(viteConfig, reactRouterConfig, serverBuildDirectory, serverBuildPath, clientBuildDirectory) {
|
|
3373
3454
|
let { build, handler } = await getPrerenderBuildAndHandler(
|
|
@@ -3376,22 +3457,29 @@ async function handlePrerender(viteConfig, reactRouterConfig, serverBuildDirecto
|
|
|
3376
3457
|
serverBuildPath
|
|
3377
3458
|
);
|
|
3378
3459
|
let routes = createPrerenderRoutes(build.routes);
|
|
3379
|
-
let
|
|
3460
|
+
let routesToPrerender;
|
|
3461
|
+
if (typeof reactRouterConfig.prerender === "boolean") {
|
|
3462
|
+
invariant(reactRouterConfig.prerender, "Expected prerender:true");
|
|
3463
|
+
routesToPrerender = determineStaticPrerenderRoutes(
|
|
3464
|
+
routes,
|
|
3465
|
+
viteConfig,
|
|
3466
|
+
true
|
|
3467
|
+
);
|
|
3468
|
+
} else if (typeof reactRouterConfig.prerender === "function") {
|
|
3469
|
+
routesToPrerender = await reactRouterConfig.prerender({
|
|
3470
|
+
getStaticPaths: () => determineStaticPrerenderRoutes(routes, viteConfig, false)
|
|
3471
|
+
});
|
|
3472
|
+
} else {
|
|
3473
|
+
routesToPrerender = reactRouterConfig.prerender || ["/"];
|
|
3474
|
+
}
|
|
3380
3475
|
let headers = {
|
|
3381
3476
|
// Header that can be used in the loader to know if you're running at
|
|
3382
3477
|
// build time or runtime
|
|
3383
3478
|
"X-React-Router-Prerender": "yes"
|
|
3384
3479
|
};
|
|
3385
|
-
for (let path7 of
|
|
3480
|
+
for (let path7 of routesToPrerender) {
|
|
3386
3481
|
let matches = (0, import_react_router2.matchRoutes)(routes, `/${path7}/`.replace(/^\/\/+/, "/"));
|
|
3387
|
-
|
|
3388
|
-
matches,
|
|
3389
|
-
`Unable to prerender path because it does not match any routes: ${path7}`
|
|
3390
|
-
);
|
|
3391
|
-
matches.forEach((m) => prerenderedRoutes.add(m.route.id));
|
|
3392
|
-
let hasLoaders = matches.some(
|
|
3393
|
-
(m) => build.assets.routes[m.route.id]?.hasLoader
|
|
3394
|
-
);
|
|
3482
|
+
let hasLoaders = matches?.some((m) => m.route.loader);
|
|
3395
3483
|
let data;
|
|
3396
3484
|
if (hasLoaders) {
|
|
3397
3485
|
data = await prerenderData(
|
|
@@ -3431,34 +3519,8 @@ async function handlePrerender(viteConfig, reactRouterConfig, serverBuildDirecto
|
|
|
3431
3519
|
);
|
|
3432
3520
|
}
|
|
3433
3521
|
}
|
|
3434
|
-
if (reactRouterConfig.ssr === false) {
|
|
3435
|
-
let errors = [];
|
|
3436
|
-
for (let [routeId, route] of Object.entries(build.routes)) {
|
|
3437
|
-
let invalidApis = [];
|
|
3438
|
-
if (route) {
|
|
3439
|
-
if (route.module.headers) invalidApis.push("headers");
|
|
3440
|
-
if (route.module.action) invalidApis.push("action");
|
|
3441
|
-
if (invalidApis.length > 0) {
|
|
3442
|
-
errors.push(
|
|
3443
|
-
`Prerender: ${invalidApis.length} invalid route export(s) in \`${route.id}\` when prerendering with \`ssr:false\`: ${invalidApis.join(", ")}. See https://reactrouter.com/how-to/spa for more information.`
|
|
3444
|
-
);
|
|
3445
|
-
}
|
|
3446
|
-
if (route.module.loader && !prerenderedRoutes.has(routeId)) {
|
|
3447
|
-
errors.push(
|
|
3448
|
-
`Prerender: 1 invalid route export in \`${route.id}\` when using \`ssr:false\` with \`prerender\` because the route is never prerendered so the loader will never be called. See https://reactrouter.com/how-to/spa for more information.`
|
|
3449
|
-
);
|
|
3450
|
-
}
|
|
3451
|
-
}
|
|
3452
|
-
}
|
|
3453
|
-
if (errors.length > 0) {
|
|
3454
|
-
viteConfig.logger.error(errors.join("\n"));
|
|
3455
|
-
throw new Error(
|
|
3456
|
-
"Invalid route exports found when prerendering with `ssr:false`"
|
|
3457
|
-
);
|
|
3458
|
-
}
|
|
3459
|
-
}
|
|
3460
3522
|
}
|
|
3461
|
-
function
|
|
3523
|
+
function determineStaticPrerenderRoutes(routes, viteConfig, isBooleanUsage = false) {
|
|
3462
3524
|
let paths = ["/"];
|
|
3463
3525
|
let paramRoutes = [];
|
|
3464
3526
|
function recurse(subtree, prefix = "") {
|
|
@@ -3478,29 +3540,28 @@ function getStaticPrerenderPaths(routes) {
|
|
|
3478
3540
|
}
|
|
3479
3541
|
}
|
|
3480
3542
|
recurse(routes);
|
|
3481
|
-
|
|
3482
|
-
|
|
3483
|
-
|
|
3484
|
-
|
|
3543
|
+
if (isBooleanUsage && paramRoutes.length > 0) {
|
|
3544
|
+
viteConfig.logger.warn(
|
|
3545
|
+
[
|
|
3546
|
+
"\u26A0\uFE0F Paths with dynamic/splat params cannot be prerendered when using `prerender: true`.",
|
|
3547
|
+
"You may want to use the `prerender()` API to prerender the following paths:",
|
|
3548
|
+
...paramRoutes.map((p) => " - " + p)
|
|
3549
|
+
].join("\n")
|
|
3550
|
+
);
|
|
3551
|
+
}
|
|
3552
|
+
return paths.map((p) => p.replace(/\/\/+/g, "/").replace(/(.+)\/$/, "$1"));
|
|
3485
3553
|
}
|
|
3486
3554
|
async function prerenderData(handler, prerenderPath, clientBuildDirectory, reactRouterConfig, viteConfig, requestInit) {
|
|
3487
3555
|
let normalizedPath = `${reactRouterConfig.basename}${prerenderPath === "/" ? "/_root.data" : `${prerenderPath.replace(/\/$/, "")}.data`}`.replace(/\/\/+/g, "/");
|
|
3488
3556
|
let request = new Request(`http://localhost${normalizedPath}`, requestInit);
|
|
3489
3557
|
let response = await handler(request);
|
|
3490
3558
|
let data = await response.text();
|
|
3491
|
-
|
|
3492
|
-
throw new Error(
|
|
3493
|
-
`Prerender (data): Received a ${response.status} status code from \`entry.server.tsx\` while prerendering the \`${path6}\` path.
|
|
3494
|
-
${normalizedPath}`
|
|
3495
|
-
);
|
|
3496
|
-
}
|
|
3559
|
+
validatePrerenderedResponse(response, data, "Prerender", normalizedPath);
|
|
3497
3560
|
let outdir = path6.relative(process.cwd(), clientBuildDirectory);
|
|
3498
3561
|
let outfile = path6.join(outdir, ...normalizedPath.split("/"));
|
|
3499
3562
|
await fse.ensureDir(path6.dirname(outfile));
|
|
3500
3563
|
await fse.outputFile(outfile, data);
|
|
3501
|
-
viteConfig.logger.info(
|
|
3502
|
-
`Prerender (data): ${prerenderPath} -> ${import_picocolors3.default.bold(outfile)}`
|
|
3503
|
-
);
|
|
3564
|
+
viteConfig.logger.info(`Prerender: Generated ${import_picocolors3.default.bold(outfile)}`);
|
|
3504
3565
|
return data;
|
|
3505
3566
|
}
|
|
3506
3567
|
async function prerenderRoute(handler, prerenderPath, clientBuildDirectory, reactRouterConfig, viteConfig, requestInit) {
|
|
@@ -3511,65 +3572,42 @@ async function prerenderRoute(handler, prerenderPath, clientBuildDirectory, reac
|
|
|
3511
3572
|
let request = new Request(`http://localhost${normalizedPath}`, requestInit);
|
|
3512
3573
|
let response = await handler(request);
|
|
3513
3574
|
let html = await response.text();
|
|
3514
|
-
|
|
3515
|
-
|
|
3516
|
-
|
|
3517
|
-
${html}`
|
|
3518
|
-
);
|
|
3575
|
+
validatePrerenderedResponse(response, html, "Prerender", normalizedPath);
|
|
3576
|
+
if (!reactRouterConfig.ssr) {
|
|
3577
|
+
validatePrerenderedHtml(html, "Prerender");
|
|
3519
3578
|
}
|
|
3520
3579
|
let outdir = path6.relative(process.cwd(), clientBuildDirectory);
|
|
3521
3580
|
let outfile = path6.join(outdir, ...normalizedPath.split("/"), "index.html");
|
|
3522
3581
|
await fse.ensureDir(path6.dirname(outfile));
|
|
3523
3582
|
await fse.outputFile(outfile, html);
|
|
3524
|
-
viteConfig.logger.info(
|
|
3525
|
-
`Prerender (html): ${prerenderPath} -> ${import_picocolors3.default.bold(outfile)}`
|
|
3526
|
-
);
|
|
3583
|
+
viteConfig.logger.info(`Prerender: Generated ${import_picocolors3.default.bold(outfile)}`);
|
|
3527
3584
|
}
|
|
3528
3585
|
async function prerenderResourceRoute(handler, prerenderPath, clientBuildDirectory, reactRouterConfig, viteConfig, requestInit) {
|
|
3529
3586
|
let normalizedPath = `${reactRouterConfig.basename}${prerenderPath}/`.replace(/\/\/+/g, "/").replace(/\/$/g, "");
|
|
3530
3587
|
let request = new Request(`http://localhost${normalizedPath}`, requestInit);
|
|
3531
3588
|
let response = await handler(request);
|
|
3532
3589
|
let text = await response.text();
|
|
3533
|
-
|
|
3534
|
-
throw new Error(
|
|
3535
|
-
`Prerender (resource): Received a ${response.status} status code from \`entry.server.tsx\` while prerendering the \`${normalizedPath}\` path.
|
|
3536
|
-
${text}`
|
|
3537
|
-
);
|
|
3538
|
-
}
|
|
3590
|
+
validatePrerenderedResponse(response, text, "Prerender", normalizedPath);
|
|
3539
3591
|
let outdir = path6.relative(process.cwd(), clientBuildDirectory);
|
|
3540
3592
|
let outfile = path6.join(outdir, ...normalizedPath.split("/"));
|
|
3541
3593
|
await fse.ensureDir(path6.dirname(outfile));
|
|
3542
3594
|
await fse.outputFile(outfile, text);
|
|
3543
|
-
viteConfig.logger.info(
|
|
3544
|
-
`Prerender (resource): ${prerenderPath} -> ${import_picocolors3.default.bold(outfile)}`
|
|
3545
|
-
);
|
|
3595
|
+
viteConfig.logger.info(`Prerender: Generated ${import_picocolors3.default.bold(outfile)}`);
|
|
3546
3596
|
}
|
|
3547
|
-
|
|
3548
|
-
|
|
3549
|
-
|
|
3550
|
-
|
|
3551
|
-
|
|
3552
|
-
|
|
3553
|
-
|
|
3554
|
-
|
|
3555
|
-
|
|
3556
|
-
|
|
3557
|
-
|
|
3558
|
-
|
|
3559
|
-
|
|
3560
|
-
)
|
|
3561
|
-
);
|
|
3562
|
-
}
|
|
3563
|
-
prerenderPaths = paths;
|
|
3564
|
-
} else if (typeof prerender === "function") {
|
|
3565
|
-
prerenderPaths = await prerender({
|
|
3566
|
-
getStaticPaths: () => getStaticPrerenderPaths(prerenderRoutes).paths
|
|
3567
|
-
});
|
|
3568
|
-
} else {
|
|
3569
|
-
prerenderPaths = prerender || ["/"];
|
|
3570
|
-
}
|
|
3597
|
+
function validatePrerenderedResponse(response, html, prefix, path7) {
|
|
3598
|
+
if (response.status !== 200) {
|
|
3599
|
+
throw new Error(
|
|
3600
|
+
`${prefix}: Received a ${response.status} status code from \`entry.server.tsx\` while prerendering the \`${path7}\` path.
|
|
3601
|
+
${html}`
|
|
3602
|
+
);
|
|
3603
|
+
}
|
|
3604
|
+
}
|
|
3605
|
+
function validatePrerenderedHtml(html, prefix) {
|
|
3606
|
+
if (!html.includes("window.__reactRouterContext =") || !html.includes("window.__reactRouterRouteModules =")) {
|
|
3607
|
+
throw new Error(
|
|
3608
|
+
`${prefix}: Did you forget to include <Scripts/> in your root route? Your pre-rendered HTML files cannot hydrate without \`<Scripts />\`.`
|
|
3609
|
+
);
|
|
3571
3610
|
}
|
|
3572
|
-
return prerenderPaths;
|
|
3573
3611
|
}
|
|
3574
3612
|
function groupRoutesByParentId2(manifest) {
|
|
3575
3613
|
let routes = {};
|
|
@@ -3587,16 +3625,19 @@ function groupRoutesByParentId2(manifest) {
|
|
|
3587
3625
|
function createPrerenderRoutes(manifest, parentId = "", routesByParentId = groupRoutesByParentId2(manifest)) {
|
|
3588
3626
|
return (routesByParentId[parentId] || []).map((route) => {
|
|
3589
3627
|
let commonRoute = {
|
|
3628
|
+
// Always include root due to default boundaries
|
|
3629
|
+
hasErrorBoundary: route.id === "root" || route.module.ErrorBoundary != null,
|
|
3590
3630
|
id: route.id,
|
|
3591
|
-
path: route.path
|
|
3631
|
+
path: route.path,
|
|
3632
|
+
loader: route.module.loader ? () => null : void 0,
|
|
3633
|
+
action: void 0,
|
|
3634
|
+
handle: route.module.handle
|
|
3592
3635
|
};
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
|
|
3596
|
-
|
|
3597
|
-
|
|
3598
|
-
}
|
|
3599
|
-
return {
|
|
3636
|
+
return route.index ? {
|
|
3637
|
+
index: true,
|
|
3638
|
+
...commonRoute
|
|
3639
|
+
} : {
|
|
3640
|
+
caseSensitive: route.caseSensitive,
|
|
3600
3641
|
children: createPrerenderRoutes(manifest, route.id, routesByParentId),
|
|
3601
3642
|
...commonRoute
|
|
3602
3643
|
};
|
|
@@ -3715,6 +3756,39 @@ function validateRouteChunks({
|
|
|
3715
3756
|
].join("\n\n")
|
|
3716
3757
|
);
|
|
3717
3758
|
}
|
|
3759
|
+
async function cleanBuildDirectory(viteConfig, ctx) {
|
|
3760
|
+
let buildDirectory = ctx.reactRouterConfig.buildDirectory;
|
|
3761
|
+
let isWithinRoot = () => {
|
|
3762
|
+
let relativePath = path6.relative(ctx.rootDirectory, buildDirectory);
|
|
3763
|
+
return !relativePath.startsWith("..") && !path6.isAbsolute(relativePath);
|
|
3764
|
+
};
|
|
3765
|
+
if (viteConfig.build.emptyOutDir ?? isWithinRoot()) {
|
|
3766
|
+
await fse.remove(buildDirectory);
|
|
3767
|
+
}
|
|
3768
|
+
}
|
|
3769
|
+
async function cleanViteManifests(environmentsOptions, ctx) {
|
|
3770
|
+
let viteManifestPaths = Object.entries(environmentsOptions).map(
|
|
3771
|
+
([environmentName, options]) => {
|
|
3772
|
+
let outDir = options.build?.outDir;
|
|
3773
|
+
invariant(outDir, `Expected build.outDir for ${environmentName}`);
|
|
3774
|
+
return path6.join(outDir, ".vite/manifest.json");
|
|
3775
|
+
}
|
|
3776
|
+
);
|
|
3777
|
+
await Promise.all(
|
|
3778
|
+
viteManifestPaths.map(async (viteManifestPath) => {
|
|
3779
|
+
let manifestExists = await fse.pathExists(viteManifestPath);
|
|
3780
|
+
if (!manifestExists) return;
|
|
3781
|
+
if (!ctx.viteManifestEnabled) {
|
|
3782
|
+
await fse.remove(viteManifestPath);
|
|
3783
|
+
}
|
|
3784
|
+
let viteDir = path6.dirname(viteManifestPath);
|
|
3785
|
+
let viteDirFiles = await fse.readdir(viteDir);
|
|
3786
|
+
if (viteDirFiles.length === 0) {
|
|
3787
|
+
await fse.remove(viteDir);
|
|
3788
|
+
}
|
|
3789
|
+
})
|
|
3790
|
+
);
|
|
3791
|
+
}
|
|
3718
3792
|
async function getBuildManifest(ctx) {
|
|
3719
3793
|
let { routes, serverBundles, appDirectory } = ctx.reactRouterConfig;
|
|
3720
3794
|
if (!serverBundles) {
|
|
@@ -3774,77 +3848,101 @@ async function getBuildManifest(ctx) {
|
|
|
3774
3848
|
);
|
|
3775
3849
|
return buildManifest;
|
|
3776
3850
|
}
|
|
3777
|
-
function
|
|
3851
|
+
function mergeEnvironmentOptions(base, ...overrides) {
|
|
3778
3852
|
let vite2 = getVite();
|
|
3779
|
-
return
|
|
3853
|
+
return overrides.reduce(
|
|
3854
|
+
(merged, override) => vite2.mergeConfig(merged, override, false),
|
|
3855
|
+
base
|
|
3856
|
+
);
|
|
3780
3857
|
}
|
|
3781
|
-
async function getEnvironmentOptionsResolvers(ctx, buildManifest) {
|
|
3858
|
+
async function getEnvironmentOptionsResolvers(ctx, buildManifest, viteCommand) {
|
|
3782
3859
|
let { serverBuildFile, serverModuleFormat } = ctx.reactRouterConfig;
|
|
3783
|
-
|
|
3860
|
+
let packageRoot = path6.dirname(
|
|
3861
|
+
require.resolve("@react-router/dev/package.json")
|
|
3862
|
+
);
|
|
3863
|
+
let { moduleSyncEnabled } = await import(`file:///${path6.join(packageRoot, "module-sync-enabled/index.mjs")}`);
|
|
3864
|
+
let vite2 = getVite();
|
|
3865
|
+
let viteServerConditions = [
|
|
3866
|
+
...vite2.defaultServerConditions ?? [],
|
|
3867
|
+
...moduleSyncEnabled ? ["module-sync"] : []
|
|
3868
|
+
];
|
|
3869
|
+
function getBaseOptions({
|
|
3784
3870
|
viteUserConfig
|
|
3785
3871
|
}) {
|
|
3786
3872
|
return {
|
|
3787
|
-
|
|
3788
|
-
|
|
3789
|
-
|
|
3790
|
-
|
|
3791
|
-
|
|
3792
|
-
|
|
3793
|
-
|
|
3794
|
-
|
|
3795
|
-
|
|
3796
|
-
|
|
3797
|
-
|
|
3798
|
-
|
|
3799
|
-
|
|
3800
|
-
userHandler
|
|
3801
|
-
|
|
3802
|
-
|
|
3873
|
+
build: {
|
|
3874
|
+
cssMinify: viteUserConfig.build?.cssMinify ?? true,
|
|
3875
|
+
manifest: true,
|
|
3876
|
+
// The manifest is enabled for all builds to detect SSR-only assets
|
|
3877
|
+
rollupOptions: {
|
|
3878
|
+
preserveEntrySignatures: "exports-only",
|
|
3879
|
+
// Silence Rollup "use client" warnings
|
|
3880
|
+
// Adapted from https://github.com/vitejs/vite-plugin-react/pull/144
|
|
3881
|
+
onwarn(warning, defaultHandler) {
|
|
3882
|
+
if (warning.code === "MODULE_LEVEL_DIRECTIVE" && warning.message.includes("use client")) {
|
|
3883
|
+
return;
|
|
3884
|
+
}
|
|
3885
|
+
let userHandler = viteUserConfig.build?.rollupOptions?.onwarn;
|
|
3886
|
+
if (userHandler) {
|
|
3887
|
+
userHandler(warning, defaultHandler);
|
|
3888
|
+
} else {
|
|
3889
|
+
defaultHandler(warning);
|
|
3890
|
+
}
|
|
3803
3891
|
}
|
|
3804
3892
|
}
|
|
3805
3893
|
}
|
|
3806
3894
|
};
|
|
3807
3895
|
}
|
|
3808
|
-
function
|
|
3896
|
+
function getBaseServerOptions({
|
|
3809
3897
|
viteUserConfig
|
|
3810
3898
|
}) {
|
|
3811
|
-
|
|
3812
|
-
|
|
3813
|
-
|
|
3814
|
-
|
|
3815
|
-
|
|
3816
|
-
|
|
3817
|
-
|
|
3818
|
-
|
|
3819
|
-
|
|
3820
|
-
|
|
3821
|
-
|
|
3822
|
-
|
|
3823
|
-
|
|
3899
|
+
let conditions = viteCommand === "build" ? viteServerConditions : ["development", ...viteServerConditions];
|
|
3900
|
+
return mergeEnvironmentOptions(getBaseOptions({ viteUserConfig }), {
|
|
3901
|
+
resolve: {
|
|
3902
|
+
external: ssrExternals,
|
|
3903
|
+
conditions,
|
|
3904
|
+
externalConditions: conditions
|
|
3905
|
+
},
|
|
3906
|
+
build: {
|
|
3907
|
+
// We move SSR-only assets to client assets. Note that the
|
|
3908
|
+
// SSR build can also emit code-split JS files (e.g. by
|
|
3909
|
+
// dynamic import) under the same assets directory
|
|
3910
|
+
// regardless of "ssrEmitAssets" option, so we also need to
|
|
3911
|
+
// keep these JS files have to be kept as-is.
|
|
3912
|
+
ssrEmitAssets: true,
|
|
3913
|
+
copyPublicDir: false,
|
|
3914
|
+
// Assets in the public directory are only used by the client
|
|
3915
|
+
rollupOptions: {
|
|
3916
|
+
output: {
|
|
3917
|
+
entryFileNames: serverBuildFile,
|
|
3918
|
+
format: serverModuleFormat
|
|
3919
|
+
}
|
|
3824
3920
|
}
|
|
3825
3921
|
}
|
|
3826
3922
|
});
|
|
3827
3923
|
}
|
|
3828
3924
|
let environmentOptionsResolvers = {
|
|
3829
|
-
client: ({ viteUserConfig }) => ({
|
|
3830
|
-
build:
|
|
3925
|
+
client: ({ viteUserConfig }) => mergeEnvironmentOptions(getBaseOptions({ viteUserConfig }), {
|
|
3926
|
+
build: {
|
|
3831
3927
|
rollupOptions: {
|
|
3832
3928
|
input: [
|
|
3833
3929
|
ctx.entryClientFilePath,
|
|
3834
|
-
...Object.values(ctx.reactRouterConfig.routes).flatMap(
|
|
3835
|
-
|
|
3836
|
-
|
|
3837
|
-
|
|
3838
|
-
|
|
3839
|
-
|
|
3840
|
-
|
|
3841
|
-
|
|
3842
|
-
|
|
3843
|
-
|
|
3844
|
-
|
|
3845
|
-
|
|
3846
|
-
|
|
3847
|
-
|
|
3930
|
+
...Object.values(ctx.reactRouterConfig.routes).flatMap(
|
|
3931
|
+
(route) => {
|
|
3932
|
+
let routeFilePath = path6.resolve(
|
|
3933
|
+
ctx.reactRouterConfig.appDirectory,
|
|
3934
|
+
route.file
|
|
3935
|
+
);
|
|
3936
|
+
let isRootRoute = route.file === ctx.reactRouterConfig.routes.root.file;
|
|
3937
|
+
let code = fse.readFileSync(routeFilePath, "utf-8");
|
|
3938
|
+
return [
|
|
3939
|
+
`${routeFilePath}${BUILD_CLIENT_ROUTE_QUERY_STRING}`,
|
|
3940
|
+
...ctx.reactRouterConfig.future.unstable_splitRouteModules && !isRootRoute ? routeChunkExportNames.map(
|
|
3941
|
+
(exportName) => code.includes(exportName) ? getRouteChunkModuleId(routeFilePath, exportName) : null
|
|
3942
|
+
) : []
|
|
3943
|
+
].filter(isNonNullable);
|
|
3944
|
+
}
|
|
3945
|
+
)
|
|
3848
3946
|
],
|
|
3849
3947
|
output: {
|
|
3850
3948
|
entryFileNames({ moduleIds }) {
|
|
@@ -3856,19 +3954,19 @@ async function getEnvironmentOptionsResolvers(ctx, buildManifest) {
|
|
|
3856
3954
|
}
|
|
3857
3955
|
},
|
|
3858
3956
|
outDir: getClientBuildDirectory(ctx.reactRouterConfig)
|
|
3859
|
-
}
|
|
3957
|
+
}
|
|
3860
3958
|
})
|
|
3861
3959
|
};
|
|
3862
3960
|
if (hasServerBundles(buildManifest)) {
|
|
3863
3961
|
for (let [serverBundleId, routes] of Object.entries(
|
|
3864
3962
|
getRoutesByServerBundleId(buildManifest)
|
|
3865
3963
|
)) {
|
|
3866
|
-
|
|
3867
|
-
|
|
3868
|
-
}) => (
|
|
3869
|
-
|
|
3870
|
-
|
|
3871
|
-
{
|
|
3964
|
+
const serverBundleEnvironmentId = serverBundleId.replaceAll("-", "_");
|
|
3965
|
+
const environmentName = `${SSR_BUNDLE_PREFIX}${serverBundleEnvironmentId}`;
|
|
3966
|
+
environmentOptionsResolvers[environmentName] = ({ viteUserConfig }) => mergeEnvironmentOptions(
|
|
3967
|
+
getBaseServerOptions({ viteUserConfig }),
|
|
3968
|
+
{
|
|
3969
|
+
build: {
|
|
3872
3970
|
outDir: getServerBuildDirectory(ctx, { serverBundleId }),
|
|
3873
3971
|
rollupOptions: {
|
|
3874
3972
|
input: `${virtual.serverBuild.id}?route-ids=${Object.keys(
|
|
@@ -3876,30 +3974,43 @@ async function getEnvironmentOptionsResolvers(ctx, buildManifest) {
|
|
|
3876
3974
|
).join(",")}`
|
|
3877
3975
|
}
|
|
3878
3976
|
}
|
|
3879
|
-
|
|
3880
|
-
|
|
3977
|
+
},
|
|
3978
|
+
// Ensure server bundle environments extend the user's SSR
|
|
3979
|
+
// environment config if it exists
|
|
3980
|
+
viteUserConfig.environments?.ssr ?? {}
|
|
3981
|
+
);
|
|
3881
3982
|
}
|
|
3882
3983
|
} else {
|
|
3883
|
-
environmentOptionsResolvers.ssr = ({ viteUserConfig }) => ({
|
|
3884
|
-
build:
|
|
3984
|
+
environmentOptionsResolvers.ssr = ({ viteUserConfig }) => mergeEnvironmentOptions(getBaseServerOptions({ viteUserConfig }), {
|
|
3985
|
+
build: {
|
|
3885
3986
|
outDir: getServerBuildDirectory(ctx),
|
|
3886
3987
|
rollupOptions: {
|
|
3887
3988
|
input: viteUserConfig.build?.rollupOptions?.input ?? virtual.serverBuild.id
|
|
3888
3989
|
}
|
|
3889
|
-
}
|
|
3990
|
+
}
|
|
3890
3991
|
});
|
|
3891
3992
|
}
|
|
3892
3993
|
return environmentOptionsResolvers;
|
|
3893
3994
|
}
|
|
3894
|
-
|
|
3895
|
-
let
|
|
3896
|
-
let
|
|
3995
|
+
function resolveEnvironmentsOptions(environmentResolvers, resolverOptions) {
|
|
3996
|
+
let environmentOptions = {};
|
|
3997
|
+
for (let [environmentName, resolver] of Object.entries(
|
|
3998
|
+
environmentResolvers
|
|
3999
|
+
)) {
|
|
4000
|
+
environmentOptions[environmentName] = resolver(resolverOptions);
|
|
4001
|
+
}
|
|
4002
|
+
return environmentOptions;
|
|
4003
|
+
}
|
|
4004
|
+
async function getEnvironmentsOptions(ctx, buildManifest, viteCommand, resolverOptions) {
|
|
4005
|
+
let environmentOptionsResolvers = await getEnvironmentOptionsResolvers(
|
|
3897
4006
|
ctx,
|
|
3898
|
-
buildManifest
|
|
4007
|
+
buildManifest,
|
|
4008
|
+
viteCommand
|
|
4009
|
+
);
|
|
4010
|
+
return resolveEnvironmentsOptions(
|
|
4011
|
+
environmentOptionsResolvers,
|
|
4012
|
+
resolverOptions
|
|
3899
4013
|
);
|
|
3900
|
-
let resolver = environmentResolvers[environmentName];
|
|
3901
|
-
invariant(resolver, `Missing environment resolver for ${environmentName}`);
|
|
3902
|
-
return resolver(resolverOptions);
|
|
3903
4014
|
}
|
|
3904
4015
|
function isNonNullable(x) {
|
|
3905
4016
|
return x != null;
|