@react-router/dev 0.0.0-experimental-8e9d8ef63 → 0.0.0-experimental-66d5af831
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 +4 -3
- package/dist/config.d.ts +1 -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 +11 -6
- package/dist/vite.js +238 -99
- package/package.json +6 -6
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-
|
|
3
|
+
* @react-router/dev v0.0.0-experimental-66d5af831
|
|
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
|
+
turboV3: reactRouterUserConfig.future?.turboV3 ?? 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
|
|
@@ -1361,7 +1362,7 @@ async function getEnvironmentOptionsResolvers(ctx, buildManifest, viteCommand) {
|
|
|
1361
1362
|
build: {
|
|
1362
1363
|
outDir: getServerBuildDirectory(ctx),
|
|
1363
1364
|
rollupOptions: {
|
|
1364
|
-
input: viteUserConfig.build?.rollupOptions?.input ?? virtual.serverBuild.id
|
|
1365
|
+
input: (ctx.reactRouterConfig.future.unstable_viteEnvironmentApi ? viteUserConfig.environments?.ssr?.build?.rollupOptions?.input : viteUserConfig.build?.rollupOptions?.input) ?? virtual.serverBuild.id
|
|
1365
1366
|
}
|
|
1366
1367
|
}
|
|
1367
1368
|
});
|
|
@@ -2058,7 +2059,7 @@ async function run2(argv = process.argv.slice(2)) {
|
|
|
2058
2059
|
return;
|
|
2059
2060
|
}
|
|
2060
2061
|
if (flags.version) {
|
|
2061
|
-
let version = require("
|
|
2062
|
+
let version = require("../../package.json").version;
|
|
2062
2063
|
console.log(version);
|
|
2063
2064
|
return;
|
|
2064
2065
|
}
|
package/dist/config.d.ts
CHANGED
|
@@ -37,6 +37,7 @@ type ServerBundlesBuildManifest = BaseBuildManifest & {
|
|
|
37
37
|
};
|
|
38
38
|
type ServerModuleFormat = "esm" | "cjs";
|
|
39
39
|
interface FutureConfig {
|
|
40
|
+
turboV3: boolean;
|
|
40
41
|
unstable_optimizeDeps: boolean;
|
|
41
42
|
/**
|
|
42
43
|
* Automatically split route modules into multiple chunks when possible.
|
package/dist/config.js
CHANGED
package/dist/routes.js
CHANGED
|
@@ -53,7 +53,7 @@ const enqueueUpdate = debounce(async () => {
|
|
|
53
53
|
needsRevalidation,
|
|
54
54
|
manifest.routes,
|
|
55
55
|
window.__reactRouterRouteModules,
|
|
56
|
-
window.__reactRouterContext.
|
|
56
|
+
window.__reactRouterContext.ssr,
|
|
57
57
|
window.__reactRouterContext.isSpaMode
|
|
58
58
|
);
|
|
59
59
|
__reactRouterDataRouter._internalSetRoutes(routes);
|
package/dist/vite/cloudflare.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @react-router/dev v0.0.0-experimental-
|
|
2
|
+
* @react-router/dev v0.0.0-experimental-66d5af831
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -477,6 +477,7 @@ async function resolveConfig({
|
|
|
477
477
|
);
|
|
478
478
|
}
|
|
479
479
|
let future = {
|
|
480
|
+
turboV3: reactRouterUserConfig.future?.turboV3 ?? false,
|
|
480
481
|
unstable_optimizeDeps: reactRouterUserConfig.future?.unstable_optimizeDeps ?? false,
|
|
481
482
|
unstable_splitRouteModules: reactRouterUserConfig.future?.unstable_splitRouteModules ?? false,
|
|
482
483
|
unstable_viteEnvironmentApi: reactRouterUserConfig.future?.unstable_viteEnvironmentApi ?? false
|
|
@@ -678,11 +679,14 @@ var cloudflareDevProxyVitePlugin = (options = {}) => {
|
|
|
678
679
|
}
|
|
679
680
|
},
|
|
680
681
|
configureServer: async (viteDevServer) => {
|
|
681
|
-
let
|
|
682
|
-
let
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
682
|
+
let context;
|
|
683
|
+
let getContext = async () => {
|
|
684
|
+
let { getPlatformProxy } = await importWrangler();
|
|
685
|
+
let { dispose, ...cloudflare } = await getPlatformProxy(
|
|
686
|
+
restOptions
|
|
687
|
+
);
|
|
688
|
+
return { cloudflare };
|
|
689
|
+
};
|
|
686
690
|
return () => {
|
|
687
691
|
if (!viteDevServer.config.server.middlewareMode) {
|
|
688
692
|
viteDevServer.middlewares.use(async (nodeReq, nodeRes, next) => {
|
|
@@ -692,6 +696,7 @@ var cloudflareDevProxyVitePlugin = (options = {}) => {
|
|
|
692
696
|
);
|
|
693
697
|
let handler = (0, import_react_router.createRequestHandler)(build, "development");
|
|
694
698
|
let req = fromNodeRequest(nodeReq, nodeRes);
|
|
699
|
+
context ??= await getContext();
|
|
695
700
|
let loadContext = getLoadContext ? await getLoadContext({ request: req, context }) : context;
|
|
696
701
|
let res = await handler(req, loadContext);
|
|
697
702
|
await toNodeRequest(res, nodeRes);
|
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-66d5af831
|
|
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
|
+
turboV3: reactRouterUserConfig.future?.turboV3 ?? 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
|
|
@@ -1857,6 +1858,8 @@ var plugin = {
|
|
|
1857
1858
|
return function Wrapped() {
|
|
1858
1859
|
const props = {
|
|
1859
1860
|
params: useParams(),
|
|
1861
|
+
loaderData: useLoaderData(),
|
|
1862
|
+
actionData: useActionData(),
|
|
1860
1863
|
};
|
|
1861
1864
|
return h(HydrateFallback, props);
|
|
1862
1865
|
};
|
|
@@ -2232,6 +2235,11 @@ var reactRouterVitePlugin = () => {
|
|
|
2232
2235
|
// Otherwise, all routes are imported as usual
|
|
2233
2236
|
ctx.reactRouterConfig.routes
|
|
2234
2237
|
);
|
|
2238
|
+
let prerenderPaths = await getPrerenderPaths(
|
|
2239
|
+
ctx.reactRouterConfig.prerender,
|
|
2240
|
+
ctx.reactRouterConfig.ssr,
|
|
2241
|
+
routes
|
|
2242
|
+
);
|
|
2235
2243
|
return `
|
|
2236
2244
|
import * as entryServer from ${JSON.stringify(
|
|
2237
2245
|
resolveFileUrl(ctx, ctx.entryServerFilePath)
|
|
@@ -2258,6 +2266,7 @@ var reactRouterVitePlugin = () => {
|
|
|
2258
2266
|
export const future = ${JSON.stringify(ctx.reactRouterConfig.future)};
|
|
2259
2267
|
export const ssr = ${ctx.reactRouterConfig.ssr};
|
|
2260
2268
|
export const isSpaMode = ${isSpaModeEnabled(ctx.reactRouterConfig)};
|
|
2269
|
+
export const prerender = ${JSON.stringify(prerenderPaths)};
|
|
2261
2270
|
export const publicPath = ${JSON.stringify(ctx.publicPath)};
|
|
2262
2271
|
export const entry = { module: entryServer };
|
|
2263
2272
|
export const routes = {
|
|
@@ -2818,7 +2827,7 @@ var reactRouterVitePlugin = () => {
|
|
|
2818
2827
|
].join("\n")
|
|
2819
2828
|
);
|
|
2820
2829
|
}
|
|
2821
|
-
if (ctx.reactRouterConfig
|
|
2830
|
+
if (isPrerenderingEnabled(ctx.reactRouterConfig)) {
|
|
2822
2831
|
await handlePrerender(
|
|
2823
2832
|
viteConfig,
|
|
2824
2833
|
ctx.reactRouterConfig,
|
|
@@ -2992,6 +3001,15 @@ var reactRouterVitePlugin = () => {
|
|
|
2992
3001
|
let reactRouterManifest = viteCommand === "build" ? (await generateReactRouterManifestsForBuild({
|
|
2993
3002
|
routeIds
|
|
2994
3003
|
})).reactRouterServerManifest : await getReactRouterManifestForDev();
|
|
3004
|
+
if (!ctx.reactRouterConfig.ssr) {
|
|
3005
|
+
invariant(viteConfig);
|
|
3006
|
+
validateSsrFalsePrerenderExports(
|
|
3007
|
+
viteConfig,
|
|
3008
|
+
ctx,
|
|
3009
|
+
reactRouterManifest,
|
|
3010
|
+
viteChildCompiler
|
|
3011
|
+
);
|
|
3012
|
+
}
|
|
2995
3013
|
return `export default ${(0, import_jsesc.default)(reactRouterManifest, {
|
|
2996
3014
|
es6: true
|
|
2997
3015
|
})};`;
|
|
@@ -3092,12 +3110,15 @@ var reactRouterVitePlugin = () => {
|
|
|
3092
3110
|
if (!route) return;
|
|
3093
3111
|
if (!options?.ssr && isSpaModeEnabled(ctx.reactRouterConfig)) {
|
|
3094
3112
|
let exportNames = getExportNames(code);
|
|
3095
|
-
let serverOnlyExports = exportNames.filter(
|
|
3096
|
-
(exp
|
|
3097
|
-
|
|
3113
|
+
let serverOnlyExports = exportNames.filter((exp) => {
|
|
3114
|
+
if (route.id === "root" && exp === "loader") {
|
|
3115
|
+
return false;
|
|
3116
|
+
}
|
|
3117
|
+
return SERVER_ONLY_ROUTE_EXPORTS.includes(exp);
|
|
3118
|
+
});
|
|
3098
3119
|
if (serverOnlyExports.length > 0) {
|
|
3099
3120
|
let str = serverOnlyExports.map((e) => `\`${e}\``).join(", ");
|
|
3100
|
-
let message = `SPA Mode: ${serverOnlyExports.length} invalid route export(s) in \`${route.file}\`: ${str}. See https://
|
|
3121
|
+
let message = `SPA Mode: ${serverOnlyExports.length} invalid route export(s) in \`${route.file}\`: ${str}. See https://reactrouter.com/how-to/spa for more information.`;
|
|
3101
3122
|
throw Error(message);
|
|
3102
3123
|
}
|
|
3103
3124
|
if (route.id !== "root") {
|
|
@@ -3105,7 +3126,7 @@ var reactRouterVitePlugin = () => {
|
|
|
3105
3126
|
(exp) => exp === "HydrateFallback"
|
|
3106
3127
|
);
|
|
3107
3128
|
if (hasHydrateFallback) {
|
|
3108
|
-
let message = `SPA Mode: Invalid \`HydrateFallback\` export found in \`${route.file}\`. \`HydrateFallback\` is only permitted on the root route in SPA Mode. See https://
|
|
3129
|
+
let message = `SPA Mode: Invalid \`HydrateFallback\` export found in \`${route.file}\`. \`HydrateFallback\` is only permitted on the root route in SPA Mode. See https://reactrouter.com/how-to/spa for more information.`;
|
|
3109
3130
|
throw Error(message);
|
|
3110
3131
|
}
|
|
3111
3132
|
}
|
|
@@ -3398,8 +3419,11 @@ async function getRouteMetadata(cache, ctx, viteChildCompiler, route, readRouteF
|
|
|
3398
3419
|
};
|
|
3399
3420
|
return info;
|
|
3400
3421
|
}
|
|
3422
|
+
function isPrerenderingEnabled(reactRouterConfig) {
|
|
3423
|
+
return reactRouterConfig.prerender != null && reactRouterConfig.prerender !== false;
|
|
3424
|
+
}
|
|
3401
3425
|
function isSpaModeEnabled(reactRouterConfig) {
|
|
3402
|
-
return reactRouterConfig.ssr === false && (reactRouterConfig
|
|
3426
|
+
return reactRouterConfig.ssr === false && !isPrerenderingEnabled(reactRouterConfig);
|
|
3403
3427
|
}
|
|
3404
3428
|
async function getPrerenderBuildAndHandler(viteConfig, serverBuildDirectory, serverBuildFile) {
|
|
3405
3429
|
let serverBuildPath = path6.join(serverBuildDirectory, serverBuildFile);
|
|
@@ -3411,20 +3435,49 @@ async function getPrerenderBuildAndHandler(viteConfig, serverBuildDirectory, ser
|
|
|
3411
3435
|
};
|
|
3412
3436
|
}
|
|
3413
3437
|
async function handleSpaMode(viteConfig, reactRouterConfig, serverBuildDirectory, serverBuildFile, clientBuildDirectory) {
|
|
3414
|
-
let { handler } = await getPrerenderBuildAndHandler(
|
|
3438
|
+
let { build, handler } = await getPrerenderBuildAndHandler(
|
|
3415
3439
|
viteConfig,
|
|
3416
3440
|
serverBuildDirectory,
|
|
3417
3441
|
serverBuildFile
|
|
3418
3442
|
);
|
|
3419
|
-
let request = new Request(`http://localhost${reactRouterConfig.basename}
|
|
3443
|
+
let request = new Request(`http://localhost${reactRouterConfig.basename}`, {
|
|
3444
|
+
headers: {
|
|
3445
|
+
// Enable SPA mode in the server runtime and only render down to the root
|
|
3446
|
+
"X-React-Router-SPA-Mode": "yes"
|
|
3447
|
+
}
|
|
3448
|
+
});
|
|
3420
3449
|
let response = await handler(request);
|
|
3421
3450
|
let html = await response.text();
|
|
3422
|
-
|
|
3423
|
-
|
|
3424
|
-
|
|
3425
|
-
|
|
3426
|
-
|
|
3427
|
-
|
|
3451
|
+
let isPrerenderSpaFallback = build.prerender.includes("/");
|
|
3452
|
+
let filename3 = isPrerenderSpaFallback ? "__spa-fallback.html" : "index.html";
|
|
3453
|
+
if (response.status !== 200) {
|
|
3454
|
+
if (isPrerenderSpaFallback) {
|
|
3455
|
+
throw new Error(
|
|
3456
|
+
`Prerender: Received a ${response.status} status code from \`entry.server.tsx\` while prerendering your \`${filename3}\` file.
|
|
3457
|
+
` + html
|
|
3458
|
+
);
|
|
3459
|
+
} else {
|
|
3460
|
+
throw new Error(
|
|
3461
|
+
`SPA Mode: Received a ${response.status} status code from \`entry.server.tsx\` while prerendering your \`${filename3}\` file.
|
|
3462
|
+
` + html
|
|
3463
|
+
);
|
|
3464
|
+
}
|
|
3465
|
+
}
|
|
3466
|
+
if (!html.includes("window.__reactRouterContext =") || !html.includes("window.__reactRouterRouteModules =")) {
|
|
3467
|
+
throw new Error(
|
|
3468
|
+
"SPA Mode: Did you forget to include `<Scripts/>` in your root route? Your pre-rendered HTML cannot hydrate without `<Scripts />`."
|
|
3469
|
+
);
|
|
3470
|
+
}
|
|
3471
|
+
await fse.writeFile(path6.join(clientBuildDirectory, filename3), html);
|
|
3472
|
+
let prettyDir = path6.relative(process.cwd(), clientBuildDirectory);
|
|
3473
|
+
let prettyPath = path6.join(prettyDir, filename3);
|
|
3474
|
+
if (build.prerender.length > 0) {
|
|
3475
|
+
viteConfig.logger.info(
|
|
3476
|
+
`Prerender (html): SPA Fallback -> ${import_picocolors3.default.bold(prettyPath)}`
|
|
3477
|
+
);
|
|
3478
|
+
} else {
|
|
3479
|
+
viteConfig.logger.info(`SPA Mode: Generated ${import_picocolors3.default.bold(prettyPath)}`);
|
|
3480
|
+
}
|
|
3428
3481
|
}
|
|
3429
3482
|
async function handlePrerender(viteConfig, reactRouterConfig, serverBuildDirectory, serverBuildPath, clientBuildDirectory) {
|
|
3430
3483
|
let { build, handler } = await getPrerenderBuildAndHandler(
|
|
@@ -3433,53 +3486,62 @@ async function handlePrerender(viteConfig, reactRouterConfig, serverBuildDirecto
|
|
|
3433
3486
|
serverBuildPath
|
|
3434
3487
|
);
|
|
3435
3488
|
let routes = createPrerenderRoutes(build.routes);
|
|
3436
|
-
let routesToPrerender;
|
|
3437
|
-
if (typeof reactRouterConfig.prerender === "boolean") {
|
|
3438
|
-
invariant(reactRouterConfig.prerender, "Expected prerender:true");
|
|
3439
|
-
routesToPrerender = determineStaticPrerenderRoutes(
|
|
3440
|
-
routes,
|
|
3441
|
-
viteConfig,
|
|
3442
|
-
true
|
|
3443
|
-
);
|
|
3444
|
-
} else if (typeof reactRouterConfig.prerender === "function") {
|
|
3445
|
-
routesToPrerender = await reactRouterConfig.prerender({
|
|
3446
|
-
getStaticPaths: () => determineStaticPrerenderRoutes(routes, viteConfig, false)
|
|
3447
|
-
});
|
|
3448
|
-
} else {
|
|
3449
|
-
routesToPrerender = reactRouterConfig.prerender || ["/"];
|
|
3450
|
-
}
|
|
3451
3489
|
let headers = {
|
|
3452
3490
|
// Header that can be used in the loader to know if you're running at
|
|
3453
3491
|
// build time or runtime
|
|
3454
3492
|
"X-React-Router-Prerender": "yes"
|
|
3455
3493
|
};
|
|
3456
|
-
for (let path7 of
|
|
3494
|
+
for (let path7 of build.prerender) {
|
|
3457
3495
|
let matches = (0, import_react_router2.matchRoutes)(routes, `/${path7}/`.replace(/^\/\/+/, "/"));
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
handler,
|
|
3463
|
-
path7,
|
|
3464
|
-
clientBuildDirectory,
|
|
3465
|
-
reactRouterConfig,
|
|
3466
|
-
viteConfig,
|
|
3467
|
-
{ headers }
|
|
3468
|
-
);
|
|
3469
|
-
}
|
|
3496
|
+
invariant(
|
|
3497
|
+
matches,
|
|
3498
|
+
`Unable to prerender path because it does not match any routes: ${path7}`
|
|
3499
|
+
);
|
|
3470
3500
|
let leafRoute = matches ? matches[matches.length - 1].route : null;
|
|
3471
3501
|
let manifestRoute = leafRoute ? build.routes[leafRoute.id]?.module : null;
|
|
3472
|
-
let isResourceRoute = manifestRoute && !manifestRoute.default && !manifestRoute.ErrorBoundary
|
|
3502
|
+
let isResourceRoute = manifestRoute && !manifestRoute.default && !manifestRoute.ErrorBoundary;
|
|
3473
3503
|
if (isResourceRoute) {
|
|
3474
|
-
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
|
|
3478
|
-
|
|
3479
|
-
|
|
3480
|
-
|
|
3481
|
-
|
|
3504
|
+
invariant(leafRoute);
|
|
3505
|
+
invariant(manifestRoute);
|
|
3506
|
+
if (manifestRoute.loader) {
|
|
3507
|
+
await prerenderData(
|
|
3508
|
+
handler,
|
|
3509
|
+
path7,
|
|
3510
|
+
[leafRoute.id],
|
|
3511
|
+
clientBuildDirectory,
|
|
3512
|
+
reactRouterConfig,
|
|
3513
|
+
viteConfig,
|
|
3514
|
+
{ headers }
|
|
3515
|
+
);
|
|
3516
|
+
await prerenderResourceRoute(
|
|
3517
|
+
handler,
|
|
3518
|
+
path7,
|
|
3519
|
+
clientBuildDirectory,
|
|
3520
|
+
reactRouterConfig,
|
|
3521
|
+
viteConfig,
|
|
3522
|
+
{ headers }
|
|
3523
|
+
);
|
|
3524
|
+
} else {
|
|
3525
|
+
viteConfig.logger.warn(
|
|
3526
|
+
`\u26A0\uFE0F Skipping prerendering for resource route without a loader: ${leafRoute?.id}`
|
|
3527
|
+
);
|
|
3528
|
+
}
|
|
3482
3529
|
} else {
|
|
3530
|
+
let hasLoaders = matches.some(
|
|
3531
|
+
(m) => build.assets.routes[m.route.id]?.hasLoader
|
|
3532
|
+
);
|
|
3533
|
+
let data;
|
|
3534
|
+
if (!isResourceRoute && hasLoaders) {
|
|
3535
|
+
data = await prerenderData(
|
|
3536
|
+
handler,
|
|
3537
|
+
path7,
|
|
3538
|
+
null,
|
|
3539
|
+
clientBuildDirectory,
|
|
3540
|
+
reactRouterConfig,
|
|
3541
|
+
viteConfig,
|
|
3542
|
+
{ headers }
|
|
3543
|
+
);
|
|
3544
|
+
}
|
|
3483
3545
|
await prerenderRoute(
|
|
3484
3546
|
handler,
|
|
3485
3547
|
path7,
|
|
@@ -3496,7 +3558,7 @@ async function handlePrerender(viteConfig, reactRouterConfig, serverBuildDirecto
|
|
|
3496
3558
|
}
|
|
3497
3559
|
}
|
|
3498
3560
|
}
|
|
3499
|
-
function
|
|
3561
|
+
function getStaticPrerenderPaths(routes) {
|
|
3500
3562
|
let paths = ["/"];
|
|
3501
3563
|
let paramRoutes = [];
|
|
3502
3564
|
function recurse(subtree, prefix = "") {
|
|
@@ -3516,28 +3578,33 @@ function determineStaticPrerenderRoutes(routes, viteConfig, isBooleanUsage = fal
|
|
|
3516
3578
|
}
|
|
3517
3579
|
}
|
|
3518
3580
|
recurse(routes);
|
|
3519
|
-
|
|
3520
|
-
|
|
3521
|
-
|
|
3522
|
-
|
|
3523
|
-
"You may want to use the `prerender()` API to prerender the following paths:",
|
|
3524
|
-
...paramRoutes.map((p) => " - " + p)
|
|
3525
|
-
].join("\n")
|
|
3526
|
-
);
|
|
3527
|
-
}
|
|
3528
|
-
return paths.map((p) => p.replace(/\/\/+/g, "/").replace(/(.+)\/$/, "$1"));
|
|
3581
|
+
return {
|
|
3582
|
+
paths: paths.map((p) => p.replace(/\/\/+/g, "/").replace(/(.+)\/$/, "$1")),
|
|
3583
|
+
paramRoutes
|
|
3584
|
+
};
|
|
3529
3585
|
}
|
|
3530
|
-
async function prerenderData(handler, prerenderPath, clientBuildDirectory, reactRouterConfig, viteConfig, requestInit) {
|
|
3586
|
+
async function prerenderData(handler, prerenderPath, onlyRoutes, clientBuildDirectory, reactRouterConfig, viteConfig, requestInit) {
|
|
3531
3587
|
let normalizedPath = `${reactRouterConfig.basename}${prerenderPath === "/" ? "/_root.data" : `${prerenderPath.replace(/\/$/, "")}.data`}`.replace(/\/\/+/g, "/");
|
|
3532
|
-
let
|
|
3588
|
+
let url2 = new URL(`http://localhost${normalizedPath}`);
|
|
3589
|
+
if (onlyRoutes?.length) {
|
|
3590
|
+
url2.searchParams.set("_routes", onlyRoutes.join(","));
|
|
3591
|
+
}
|
|
3592
|
+
let request = new Request(url2, requestInit);
|
|
3533
3593
|
let response = await handler(request);
|
|
3534
3594
|
let data = await response.text();
|
|
3535
|
-
|
|
3595
|
+
if (response.status !== 200) {
|
|
3596
|
+
throw new Error(
|
|
3597
|
+
`Prerender (data): Received a ${response.status} status code from \`entry.server.tsx\` while prerendering the \`${path6}\` path.
|
|
3598
|
+
${normalizedPath}`
|
|
3599
|
+
);
|
|
3600
|
+
}
|
|
3536
3601
|
let outdir = path6.relative(process.cwd(), clientBuildDirectory);
|
|
3537
3602
|
let outfile = path6.join(outdir, ...normalizedPath.split("/"));
|
|
3538
3603
|
await fse.ensureDir(path6.dirname(outfile));
|
|
3539
3604
|
await fse.outputFile(outfile, data);
|
|
3540
|
-
viteConfig.logger.info(
|
|
3605
|
+
viteConfig.logger.info(
|
|
3606
|
+
`Prerender (data): ${prerenderPath} -> ${import_picocolors3.default.bold(outfile)}`
|
|
3607
|
+
);
|
|
3541
3608
|
return data;
|
|
3542
3609
|
}
|
|
3543
3610
|
async function prerenderRoute(handler, prerenderPath, clientBuildDirectory, reactRouterConfig, viteConfig, requestInit) {
|
|
@@ -3548,42 +3615,65 @@ async function prerenderRoute(handler, prerenderPath, clientBuildDirectory, reac
|
|
|
3548
3615
|
let request = new Request(`http://localhost${normalizedPath}`, requestInit);
|
|
3549
3616
|
let response = await handler(request);
|
|
3550
3617
|
let html = await response.text();
|
|
3551
|
-
|
|
3552
|
-
|
|
3553
|
-
|
|
3618
|
+
if (response.status !== 200) {
|
|
3619
|
+
throw new Error(
|
|
3620
|
+
`Prerender (html): Received a ${response.status} status code from \`entry.server.tsx\` while prerendering the \`${normalizedPath}\` path.
|
|
3621
|
+
${html}`
|
|
3622
|
+
);
|
|
3554
3623
|
}
|
|
3555
3624
|
let outdir = path6.relative(process.cwd(), clientBuildDirectory);
|
|
3556
3625
|
let outfile = path6.join(outdir, ...normalizedPath.split("/"), "index.html");
|
|
3557
3626
|
await fse.ensureDir(path6.dirname(outfile));
|
|
3558
3627
|
await fse.outputFile(outfile, html);
|
|
3559
|
-
viteConfig.logger.info(
|
|
3628
|
+
viteConfig.logger.info(
|
|
3629
|
+
`Prerender (html): ${prerenderPath} -> ${import_picocolors3.default.bold(outfile)}`
|
|
3630
|
+
);
|
|
3560
3631
|
}
|
|
3561
3632
|
async function prerenderResourceRoute(handler, prerenderPath, clientBuildDirectory, reactRouterConfig, viteConfig, requestInit) {
|
|
3562
3633
|
let normalizedPath = `${reactRouterConfig.basename}${prerenderPath}/`.replace(/\/\/+/g, "/").replace(/\/$/g, "");
|
|
3563
3634
|
let request = new Request(`http://localhost${normalizedPath}`, requestInit);
|
|
3564
3635
|
let response = await handler(request);
|
|
3565
3636
|
let text = await response.text();
|
|
3566
|
-
validatePrerenderedResponse(response, text, "Prerender", normalizedPath);
|
|
3567
|
-
let outdir = path6.relative(process.cwd(), clientBuildDirectory);
|
|
3568
|
-
let outfile = path6.join(outdir, ...normalizedPath.split("/"));
|
|
3569
|
-
await fse.ensureDir(path6.dirname(outfile));
|
|
3570
|
-
await fse.outputFile(outfile, text);
|
|
3571
|
-
viteConfig.logger.info(`Prerender: Generated ${import_picocolors3.default.bold(outfile)}`);
|
|
3572
|
-
}
|
|
3573
|
-
function validatePrerenderedResponse(response, html, prefix, path7) {
|
|
3574
3637
|
if (response.status !== 200) {
|
|
3575
3638
|
throw new Error(
|
|
3576
|
-
|
|
3577
|
-
${
|
|
3639
|
+
`Prerender (resource): Received a ${response.status} status code from \`entry.server.tsx\` while prerendering the \`${normalizedPath}\` path.
|
|
3640
|
+
${text}`
|
|
3578
3641
|
);
|
|
3579
3642
|
}
|
|
3643
|
+
let outdir = path6.relative(process.cwd(), clientBuildDirectory);
|
|
3644
|
+
let outfile = path6.join(outdir, ...normalizedPath.split("/"));
|
|
3645
|
+
await fse.ensureDir(path6.dirname(outfile));
|
|
3646
|
+
await fse.outputFile(outfile, text);
|
|
3647
|
+
viteConfig.logger.info(
|
|
3648
|
+
`Prerender (resource): ${prerenderPath} -> ${import_picocolors3.default.bold(outfile)}`
|
|
3649
|
+
);
|
|
3580
3650
|
}
|
|
3581
|
-
function
|
|
3582
|
-
|
|
3583
|
-
|
|
3584
|
-
|
|
3585
|
-
)
|
|
3651
|
+
async function getPrerenderPaths(prerender, ssr, routes, logWarning = false) {
|
|
3652
|
+
let prerenderPaths = [];
|
|
3653
|
+
if (prerender != null && prerender !== false) {
|
|
3654
|
+
let prerenderRoutes = createPrerenderRoutes(routes);
|
|
3655
|
+
if (prerender === true) {
|
|
3656
|
+
let { paths, paramRoutes } = getStaticPrerenderPaths(prerenderRoutes);
|
|
3657
|
+
if (logWarning && !ssr && paramRoutes.length > 0) {
|
|
3658
|
+
console.warn(
|
|
3659
|
+
import_picocolors3.default.yellow(
|
|
3660
|
+
[
|
|
3661
|
+
"\u26A0\uFE0F Paths with dynamic/splat params cannot be prerendered when using `prerender: true`. You may want to use the `prerender()` API to prerender the following paths:",
|
|
3662
|
+
...paramRoutes.map((p) => " - " + p)
|
|
3663
|
+
].join("\n")
|
|
3664
|
+
)
|
|
3665
|
+
);
|
|
3666
|
+
}
|
|
3667
|
+
prerenderPaths = paths;
|
|
3668
|
+
} else if (typeof prerender === "function") {
|
|
3669
|
+
prerenderPaths = await prerender({
|
|
3670
|
+
getStaticPaths: () => getStaticPrerenderPaths(prerenderRoutes).paths
|
|
3671
|
+
});
|
|
3672
|
+
} else {
|
|
3673
|
+
prerenderPaths = prerender || ["/"];
|
|
3674
|
+
}
|
|
3586
3675
|
}
|
|
3676
|
+
return prerenderPaths;
|
|
3587
3677
|
}
|
|
3588
3678
|
function groupRoutesByParentId2(manifest) {
|
|
3589
3679
|
let routes = {};
|
|
@@ -3601,24 +3691,73 @@ function groupRoutesByParentId2(manifest) {
|
|
|
3601
3691
|
function createPrerenderRoutes(manifest, parentId = "", routesByParentId = groupRoutesByParentId2(manifest)) {
|
|
3602
3692
|
return (routesByParentId[parentId] || []).map((route) => {
|
|
3603
3693
|
let commonRoute = {
|
|
3604
|
-
// Always include root due to default boundaries
|
|
3605
|
-
hasErrorBoundary: route.id === "root" || route.module.ErrorBoundary != null,
|
|
3606
3694
|
id: route.id,
|
|
3607
|
-
path: route.path
|
|
3608
|
-
loader: route.module.loader ? () => null : void 0,
|
|
3609
|
-
action: void 0,
|
|
3610
|
-
handle: route.module.handle
|
|
3695
|
+
path: route.path
|
|
3611
3696
|
};
|
|
3612
|
-
|
|
3613
|
-
|
|
3614
|
-
|
|
3615
|
-
|
|
3616
|
-
|
|
3697
|
+
if (route.index) {
|
|
3698
|
+
return {
|
|
3699
|
+
index: true,
|
|
3700
|
+
...commonRoute
|
|
3701
|
+
};
|
|
3702
|
+
}
|
|
3703
|
+
return {
|
|
3617
3704
|
children: createPrerenderRoutes(manifest, route.id, routesByParentId),
|
|
3618
3705
|
...commonRoute
|
|
3619
3706
|
};
|
|
3620
3707
|
});
|
|
3621
3708
|
}
|
|
3709
|
+
async function validateSsrFalsePrerenderExports(viteConfig, ctx, manifest, viteChildCompiler) {
|
|
3710
|
+
let prerenderPaths = await getPrerenderPaths(
|
|
3711
|
+
ctx.reactRouterConfig.prerender,
|
|
3712
|
+
ctx.reactRouterConfig.ssr,
|
|
3713
|
+
manifest.routes,
|
|
3714
|
+
true
|
|
3715
|
+
);
|
|
3716
|
+
if (prerenderPaths.length === 0) {
|
|
3717
|
+
return;
|
|
3718
|
+
}
|
|
3719
|
+
let prerenderRoutes = createPrerenderRoutes(manifest.routes);
|
|
3720
|
+
let prerenderedRoutes = /* @__PURE__ */ new Set();
|
|
3721
|
+
for (let path7 of prerenderPaths) {
|
|
3722
|
+
let matches = (0, import_react_router2.matchRoutes)(
|
|
3723
|
+
prerenderRoutes,
|
|
3724
|
+
`/${path7}/`.replace(/^\/\/+/, "/")
|
|
3725
|
+
);
|
|
3726
|
+
invariant(
|
|
3727
|
+
matches,
|
|
3728
|
+
`Unable to prerender path because it does not match any routes: ${path7}`
|
|
3729
|
+
);
|
|
3730
|
+
matches.forEach((m) => prerenderedRoutes.add(m.route.id));
|
|
3731
|
+
}
|
|
3732
|
+
let errors = [];
|
|
3733
|
+
let routeExports = await getRouteManifestModuleExports(
|
|
3734
|
+
viteChildCompiler,
|
|
3735
|
+
ctx
|
|
3736
|
+
);
|
|
3737
|
+
for (let [routeId, route] of Object.entries(manifest.routes)) {
|
|
3738
|
+
let invalidApis = [];
|
|
3739
|
+
invariant(route, "Expected a route object in validateSsrFalseExports");
|
|
3740
|
+
let exports2 = routeExports[route.id];
|
|
3741
|
+
if (exports2.includes("headers")) invalidApis.push("headers");
|
|
3742
|
+
if (exports2.includes("action")) invalidApis.push("action");
|
|
3743
|
+
if (invalidApis.length > 0) {
|
|
3744
|
+
errors.push(
|
|
3745
|
+
`Prerender: ${invalidApis.length} invalid route export(s) in \`${route.id}\` when prerendering with \`ssr:false\`: ${invalidApis.join(", ")}. See https://reactrouter.com/how-to/pre-rendering for more information.`
|
|
3746
|
+
);
|
|
3747
|
+
}
|
|
3748
|
+
if (exports2.includes("loader") && !prerenderedRoutes.has(routeId)) {
|
|
3749
|
+
errors.push(
|
|
3750
|
+
`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/pre-rendering for more information.`
|
|
3751
|
+
);
|
|
3752
|
+
}
|
|
3753
|
+
}
|
|
3754
|
+
if (errors.length > 0) {
|
|
3755
|
+
viteConfig.logger.error(import_picocolors3.default.red(errors.join("\n")));
|
|
3756
|
+
throw new Error(
|
|
3757
|
+
"Invalid route exports found when prerendering with `ssr:false`"
|
|
3758
|
+
);
|
|
3759
|
+
}
|
|
3760
|
+
}
|
|
3622
3761
|
function getAddressableRoutes(routes) {
|
|
3623
3762
|
let nonAddressableIds = /* @__PURE__ */ new Set();
|
|
3624
3763
|
for (let id in routes) {
|
|
@@ -3961,7 +4100,7 @@ async function getEnvironmentOptionsResolvers(ctx, buildManifest, viteCommand) {
|
|
|
3961
4100
|
build: {
|
|
3962
4101
|
outDir: getServerBuildDirectory(ctx),
|
|
3963
4102
|
rollupOptions: {
|
|
3964
|
-
input: viteUserConfig.build?.rollupOptions?.input ?? virtual.serverBuild.id
|
|
4103
|
+
input: (ctx.reactRouterConfig.future.unstable_viteEnvironmentApi ? viteUserConfig.environments?.ssr?.build?.rollupOptions?.input : viteUserConfig.build?.rollupOptions?.input) ?? virtual.serverBuild.id
|
|
3965
4104
|
}
|
|
3966
4105
|
}
|
|
3967
4106
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@react-router/dev",
|
|
3
|
-
"version": "0.0.0-experimental-
|
|
3
|
+
"version": "0.0.0-experimental-66d5af831",
|
|
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-
|
|
91
|
+
"@react-router/node": "0.0.0-experimental-66d5af831"
|
|
92
92
|
},
|
|
93
93
|
"devDependencies": {
|
|
94
94
|
"@types/babel__core": "^7.20.5",
|
|
@@ -117,15 +117,15 @@
|
|
|
117
117
|
"vite": "^6.0.0",
|
|
118
118
|
"wireit": "0.14.9",
|
|
119
119
|
"wrangler": "^3.28.2",
|
|
120
|
-
"react-router": "^0.0.0-experimental-
|
|
121
|
-
"@react-router/serve": "0.0.0-experimental-
|
|
120
|
+
"react-router": "^0.0.0-experimental-66d5af831",
|
|
121
|
+
"@react-router/serve": "0.0.0-experimental-66d5af831"
|
|
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-
|
|
128
|
-
"react-router": "^0.0.0-experimental-
|
|
127
|
+
"@react-router/serve": "^0.0.0-experimental-66d5af831",
|
|
128
|
+
"react-router": "^0.0.0-experimental-66d5af831"
|
|
129
129
|
},
|
|
130
130
|
"peerDependenciesMeta": {
|
|
131
131
|
"@react-router/serve": {
|