@@ -79,7 +79,7 @@ import {
7979 createConfigLoader ,
8080 resolveEntryFiles ,
8181 configRouteToBranchRoute ,
82- type PrerenderPaths ,
82+ PrerenderPaths ,
8383} from "../config/config" ;
8484import { getOptimizeDepsEntries } from "./optimize-deps-entries" ;
8585import { decorateComponentExportsWithProps } from "./with-props" ;
@@ -2660,81 +2660,93 @@ async function handlePrerender(
26602660 }
26612661
26622662 let buildRoutes = createPrerenderRoutes ( build . routes ) ;
2663- const concurrency = getPrerenderConcurrency ( reactRouterConfig . prerender ) ;
2664- await pMap ( build . prerender , async path => {
2665- // Ensure we have a leading slash for matching
2666- let matches = matchRoutes ( buildRoutes , `/${ path } /` . replace ( / ^ \/ \/ + / , "/" ) ) ;
2667- if ( ! matches ) {
2668- return
2669- }
2670- // When prerendering a resource route, we don't want to pass along the
2671- // `.data` file since we want to prerender the raw Response returned from
2672- // the loader. Presumably this is for routes where a file extension is
2673- // already included, such as `app/routes/items[.json].tsx` that will
2674- // render into `/items.json`
2675- let leafRoute = matches ? matches [ matches . length - 1 ] . route : null ;
2676- let manifestRoute = leafRoute ? build . routes [ leafRoute . id ] ?. module : null ;
2677- let isResourceRoute =
2678- manifestRoute && ! manifestRoute . default && ! manifestRoute . ErrorBoundary ;
2679-
2680- if ( isResourceRoute ) {
2681- invariant ( leafRoute ) ;
2682- invariant ( manifestRoute ) ;
2683- if ( manifestRoute . loader ) {
2684- // Prerender a .data file for turbo-stream consumption
2685- await prerenderData (
2686- handler ,
2687- path ,
2688- [ leafRoute . id ] ,
2689- clientBuildDirectory ,
2690- reactRouterConfig ,
2691- viteConfig ,
2692- ) ;
2693- // Prerender a raw file for external consumption
2694- await prerenderResourceRoute (
2695- handler ,
2696- path ,
2697- clientBuildDirectory ,
2698- reactRouterConfig ,
2699- viteConfig ,
2700- ) ;
2663+ await pMap (
2664+ build . prerender ,
2665+ async ( path ) => {
2666+ // Ensure we have a leading slash for matching
2667+ let matches = matchRoutes (
2668+ buildRoutes ,
2669+ `/${ path } /` . replace ( / ^ \/ \/ + / , "/" ) ,
2670+ ) ;
2671+ if ( ! matches ) {
2672+ return ;
2673+ }
2674+ // When prerendering a resource route, we don't want to pass along the
2675+ // `.data` file since we want to prerender the raw Response returned from
2676+ // the loader. Presumably this is for routes where a file extension is
2677+ // already included, such as `app/routes/items[.json].tsx` that will
2678+ // render into `/items.json`
2679+ let leafRoute = matches ? matches [ matches . length - 1 ] . route : null ;
2680+ let manifestRoute = leafRoute ? build . routes [ leafRoute . id ] ?. module : null ;
2681+ let isResourceRoute =
2682+ manifestRoute && ! manifestRoute . default && ! manifestRoute . ErrorBoundary ;
2683+
2684+ if ( isResourceRoute ) {
2685+ invariant ( leafRoute ) ;
2686+ invariant ( manifestRoute ) ;
2687+ if ( manifestRoute . loader ) {
2688+ // Prerender a .data file for turbo-stream consumption
2689+ await prerenderData (
2690+ handler ,
2691+ path ,
2692+ [ leafRoute . id ] ,
2693+ clientBuildDirectory ,
2694+ reactRouterConfig ,
2695+ viteConfig ,
2696+ ) ;
2697+ // Prerender a raw file for external consumption
2698+ await prerenderResourceRoute (
2699+ handler ,
2700+ path ,
2701+ clientBuildDirectory ,
2702+ reactRouterConfig ,
2703+ viteConfig ,
2704+ ) ;
2705+ } else {
2706+ viteConfig . logger . warn (
2707+ `⚠️ Skipping prerendering for resource route without a loader: ${ leafRoute ?. id } ` ,
2708+ ) ;
2709+ }
27012710 } else {
2702- viteConfig . logger . warn (
2703- `⚠️ Skipping prerendering for resource route without a loader: ${ leafRoute ? .id } ` ,
2711+ let hasLoaders = matches . some (
2712+ ( m ) => build . assets . routes [ m . route . id ] ?. hasLoader ,
27042713 ) ;
2705- }
2706- } else {
2707- let hasLoaders = matches . some (
2708- ( m ) => build . assets . routes [ m . route . id ] ?. hasLoader ,
2709- ) ;
2710- let data : string | undefined ;
2711- if ( ! isResourceRoute && hasLoaders ) {
2712- data = await prerenderData (
2714+ let data : string | undefined ;
2715+ if ( ! isResourceRoute && hasLoaders ) {
2716+ data = await prerenderData (
2717+ handler ,
2718+ path ,
2719+ null ,
2720+ clientBuildDirectory ,
2721+ reactRouterConfig ,
2722+ viteConfig ,
2723+ ) ;
2724+ }
2725+
2726+ await prerenderRoute (
27132727 handler ,
27142728 path ,
2715- null ,
27162729 clientBuildDirectory ,
27172730 reactRouterConfig ,
27182731 viteConfig ,
2732+ data
2733+ ? {
2734+ headers : {
2735+ "X-React-Router-Prerender-Data" : encodeURI ( data ) ,
2736+ } ,
2737+ }
2738+ : undefined ,
27192739 ) ;
27202740 }
2721-
2722- await prerenderRoute (
2723- handler ,
2724- path ,
2725- clientBuildDirectory ,
2726- reactRouterConfig ,
2727- viteConfig ,
2728- data
2729- ? {
2730- headers : {
2731- "X-React-Router-Prerender-Data" : encodeURI ( data ) ,
2732- } ,
2733- }
2734- : undefined ,
2735- ) ;
2736- }
2737- } , { concurrency } ) ;
2741+ } ,
2742+ {
2743+ concurrency :
2744+ typeof reactRouterConfig . prerender === "object" &&
2745+ "paths" in reactRouterConfig . prerender
2746+ ? reactRouterConfig . prerender . unstable_concurrency || 1
2747+ : 1 ,
2748+ } ,
2749+ ) ;
27382750}
27392751
27402752function getStaticPrerenderPaths ( routes : DataRouteObject [ ] ) {
@@ -2919,48 +2931,49 @@ export async function getPrerenderPaths(
29192931 routes : GenericRouteManifest ,
29202932 logWarning = false ,
29212933) : Promise < string [ ] > {
2922- let prerenderPaths : string [ ] = [ ] ;
2923- if ( prerender != null && prerender !== false ) {
2924- let prerenderRoutes = createPrerenderRoutes ( routes ) ;
2925- if ( typeof prerender === "object" ) {
2926- prerender = ( prerender as { paths : PrerenderPaths } ) . paths
2927- }
2934+ if ( prerender == null || prerender === false ) {
2935+ return [ ] ;
2936+ }
29282937
2929- if ( prerender === true ) {
2930- let { paths, paramRoutes } = getStaticPrerenderPaths ( prerenderRoutes ) ;
2931- if ( logWarning && ! ssr && paramRoutes . length > 0 ) {
2932- console . warn (
2933- colors . yellow (
2934- [
2935- "⚠️ Paths with dynamic/splat params cannot be prerendered when " +
2936- "using `prerender: true`. You may want to use the `prerender()` " +
2937- "API to prerender the following paths:" ,
2938- ...paramRoutes . map ( ( p ) => " - " + p ) ,
2939- ] . join ( "\n" ) ,
2940- ) ,
2941- ) ;
2942- }
2943- prerenderPaths = paths ;
2944- } else if ( typeof prerender === "function" ) {
2945- prerenderPaths = await prerender ( {
2946- getStaticPaths : ( ) => getStaticPrerenderPaths ( prerenderRoutes ) . paths ,
2947- } ) ;
2948- } else {
2949- prerenderPaths = prerender || [ "/" ] ;
2950- }
2938+ let pathsConfig : PrerenderPaths ;
2939+
2940+ if ( typeof prerender === "object" && "paths" in prerender ) {
2941+ pathsConfig = prerender . paths ;
2942+ } else {
2943+ pathsConfig = prerender ;
29512944 }
2952- return prerenderPaths ;
2953- }
29542945
2955- const DEFAULT_PRERENDER_CONCURRENCY = 1
2946+ if ( pathsConfig === false ) {
2947+ return [ ] ;
2948+ }
29562949
2957- function getPrerenderConcurrency (
2958- prerender : ResolvedReactRouterConfig [ "prerender" ] ,
2959- ) : number {
2960- if ( typeof prerender === "object" ) {
2961- return ( prerender as { unstable_concurrency ?: number } ) . unstable_concurrency || DEFAULT_PRERENDER_CONCURRENCY
2950+ let prerenderRoutes = createPrerenderRoutes ( routes ) ;
2951+
2952+ if ( pathsConfig === true ) {
2953+ let { paths, paramRoutes } = getStaticPrerenderPaths ( prerenderRoutes ) ;
2954+ if ( logWarning && ! ssr && paramRoutes . length > 0 ) {
2955+ console . warn (
2956+ colors . yellow (
2957+ [
2958+ "⚠️ Paths with dynamic/splat params cannot be prerendered when " +
2959+ "using `prerender: true`. You may want to use the `prerender()` " +
2960+ "API to prerender the following paths:" ,
2961+ ...paramRoutes . map ( ( p ) => " - " + p ) ,
2962+ ] . join ( "\n" ) ,
2963+ ) ,
2964+ ) ;
2965+ }
2966+ return paths ;
29622967 }
2963- return DEFAULT_PRERENDER_CONCURRENCY
2968+
2969+ if ( typeof pathsConfig === "function" ) {
2970+ let paths = await pathsConfig ( {
2971+ getStaticPaths : ( ) => getStaticPrerenderPaths ( prerenderRoutes ) . paths ,
2972+ } ) ;
2973+ return paths ;
2974+ }
2975+
2976+ return pathsConfig ;
29642977}
29652978
29662979// Note: Duplicated from react-router/lib/server-runtime
0 commit comments