@@ -174,37 +174,50 @@ export interface AdapterOutput {
174174 /**
175175 * fallback is initial cache data generated during build for a prerender
176176 */
177- fallback ?: {
178- /**
179- * path to the fallback file can be HTML/JSON/RSC
180- */
181- filePath : string
182- /**
183- * initialStatus is the status code that should be applied
184- * when serving the fallback
185- */
186- initialStatus ?: number
187- /**
188- * initialHeaders are the headers that should be sent when
189- * serving the fallback
190- */
191- initialHeaders ?: Record < string , string | string [ ] >
192- /**
193- * initial expiration is how long until the fallback entry
194- * is considered expired and no longer valid to serve
195- */
196- initialExpiration ?: number
197- /**
198- * initial revalidate is how long until the fallback is
199- * considered stale and should be revalidated
200- */
201- initialRevalidate ?: Revalidate
202-
203- /**
204- * postponedState is the PPR state when it postponed and is used for resuming
205- */
206- postponedState ?: string
207- }
177+ fallback ?:
178+ | {
179+ /**
180+ * path to the fallback file can be HTML/JSON/RSC,
181+ */
182+ filePath : string
183+ /**
184+ * initialStatus is the status code that should be applied
185+ * when serving the fallback
186+ */
187+ initialStatus ?: number
188+ /**
189+ * initialHeaders are the headers that should be sent when
190+ * serving the fallback
191+ */
192+ initialHeaders ?: Record < string , string | string [ ] >
193+ /**
194+ * initial expiration is how long until the fallback entry
195+ * is considered expired and no longer valid to serve
196+ */
197+ initialExpiration ?: number
198+ /**
199+ * initial revalidate is how long until the fallback is
200+ * considered stale and should be revalidated
201+ */
202+ initialRevalidate ?: Revalidate
203+
204+ /**
205+ * postponedState is the PPR state when it postponed and is used for resuming
206+ */
207+ postponedState ?: string
208+ }
209+ | {
210+ /*
211+ a fallback filePath can be omitted when postponedState is
212+ present which signals the fallback should just resume with
213+ the postpone state but doesn't have fallback to seed cache
214+ */
215+ postponedState : string
216+ initialExpiration ?: number
217+ initialRevalidate ?: Revalidate
218+ initialHeaders ?: Record < string , string | string [ ] >
219+ initialStatus ?: number
220+ }
208221 /**
209222 * config related to the route
210223 */
@@ -1164,7 +1177,6 @@ export async function handleBuildComplete({
11641177 initialRevalidateSeconds : initialRevalidate ,
11651178 initialHeaders,
11661179 initialStatus,
1167- prefetchDataRoute,
11681180 dataRoute,
11691181 renderingMode,
11701182 allowHeader,
@@ -1273,43 +1285,64 @@ export async function handleBuildComplete({
12731285 outputs . prerenders . push ( initialOutput )
12741286
12751287 if ( dataRoute ) {
1276- let dataFilePath = path . join (
1288+ let dataFilePath : string | undefined = path . join (
12771289 pagesDistDir ,
12781290 `${ normalizePagePath ( route ) } .json`
12791291 )
1292+ let postponed = meta . postponed
12801293
12811294 if ( isAppPage ) {
12821295 // When experimental PPR is enabled, we expect that the data
12831296 // that should be served as a part of the prerender should
12841297 // be from the prefetch data route. If this isn't enabled
12851298 // for ppr, the only way to get the data is from the data
12861299 // route.
1287- dataFilePath = path . join (
1288- appDistDir ,
1289- prefetchDataRoute &&
1290- renderingMode === RenderingMode . PARTIALLY_STATIC
1291- ? prefetchDataRoute
1292- : dataRoute
1293- )
1300+ dataFilePath = path . join ( appDistDir , dataRoute )
12941301 }
12951302
1296- outputs . prerenders . push ( {
1297- ...initialOutput ,
1298- id : dataRoute ,
1299- pathname : dataRoute ,
1300- fallback : isNotFoundTrue
1301- ? undefined
1302- : {
1303- ...initialOutput . fallback ,
1304- initialHeaders : {
1305- ...initialOutput . fallback ?. initialHeaders ,
1306- 'content-type' : isAppPage
1307- ? rscContentTypeHeader
1308- : JSON_CONTENT_TYPE_HEADER ,
1303+ if (
1304+ renderingMode === RenderingMode . PARTIALLY_STATIC &&
1305+ ! ( await cachedFilePathCheck ( dataFilePath ) )
1306+ ) {
1307+ // TODO: allowQuery should diverge based on app client param
1308+ // parsing flag
1309+ outputs . prerenders . push ( {
1310+ ...initialOutput ,
1311+ id : dataRoute ,
1312+ pathname : dataRoute ,
1313+ fallback : ! postponed
1314+ ? undefined
1315+ : {
1316+ ...initialOutput . fallback ,
1317+ postponedState : postponed ,
1318+ initialHeaders : {
1319+ ...initialOutput . fallback ?. initialHeaders ,
1320+ 'content-type' : isAppPage
1321+ ? rscContentTypeHeader
1322+ : JSON_CONTENT_TYPE_HEADER ,
1323+ } ,
1324+ filePath : undefined ,
13091325 } ,
1310- filePath : dataFilePath ,
1311- } ,
1312- } )
1326+ } )
1327+ } else {
1328+ outputs . prerenders . push ( {
1329+ ...initialOutput ,
1330+ id : dataRoute ,
1331+ pathname : dataRoute ,
1332+ fallback : isNotFoundTrue
1333+ ? undefined
1334+ : {
1335+ ...initialOutput . fallback ,
1336+ initialHeaders : {
1337+ ...initialOutput . fallback ?. initialHeaders ,
1338+ 'content-type' : isAppPage
1339+ ? rscContentTypeHeader
1340+ : JSON_CONTENT_TYPE_HEADER ,
1341+ } ,
1342+ filePath : dataFilePath ,
1343+ } ,
1344+ } )
1345+ }
13131346 }
13141347
13151348 if ( isAppPage ) {
@@ -1325,13 +1358,16 @@ export async function handleBuildComplete({
13251358 fallbackRevalidate,
13261359 fallbackHeaders,
13271360 fallbackStatus,
1361+ fallbackSourceRoute,
13281362 allowHeader,
13291363 dataRoute,
13301364 renderingMode,
13311365 experimentalBypassFor,
13321366 } = prerenderManifest . dynamicRoutes [ dynamicRoute ]
13331367
1334- const isAppPage = Boolean ( appOutputMap [ dynamicRoute ] )
1368+ const srcRoute = fallbackSourceRoute || dynamicRoute
1369+ const parentOutput = getParentOutput ( srcRoute , dynamicRoute )
1370+ const isAppPage = Boolean ( appOutputMap [ srcRoute ] )
13351371
13361372 const allowQuery = Object . values (
13371373 routesManifest . dynamicRoutes . find (
@@ -1344,7 +1380,7 @@ export async function handleBuildComplete({
13441380 id : dynamicRoute ,
13451381 type : AdapterOutputType . PRERENDER ,
13461382 pathname : dynamicRoute ,
1347- parentOutputId : getParentOutput ( dynamicRoute , dynamicRoute ) . id ,
1383+ parentOutputId : parentOutput . id ,
13481384 groupId : prerenderGroupId ,
13491385 config : {
13501386 allowQuery,
@@ -1380,7 +1416,25 @@ export async function handleBuildComplete({
13801416 await handleAppMeta ( dynamicRoute , initialOutput , meta )
13811417 }
13821418
1383- if ( dataRoute ) {
1419+ if ( renderingMode === RenderingMode . PARTIALLY_STATIC ) {
1420+ outputs . prerenders . push ( {
1421+ ...initialOutput ,
1422+ id : `${ dynamicRoute } .rsc` ,
1423+ pathname : `${ dynamicRoute } .rsc` ,
1424+ fallback : meta . postponed
1425+ ? {
1426+ ...initialOutput . fallback ,
1427+ postponedState : meta . postponed ,
1428+ initialHeaders : {
1429+ ...initialOutput . fallback ?. initialHeaders ,
1430+ 'content-type' : isAppPage
1431+ ? rscContentTypeHeader
1432+ : JSON_CONTENT_TYPE_HEADER ,
1433+ } ,
1434+ }
1435+ : undefined ,
1436+ } )
1437+ } else if ( dataRoute ) {
13841438 outputs . prerenders . push ( {
13851439 ...initialOutput ,
13861440 id : dataRoute ,
@@ -1521,7 +1575,7 @@ export async function handleBuildComplete({
15211575 route . page
15221576 ) + getDestinationQuery ( route . routeKeys )
15231577
1524- if ( appPageKeys && appPageKeys . length > 0 && config . cacheComponents ) {
1578+ if ( appPageKeys && appPageKeys . length > 0 ) {
15251579 // If we have fallback root params (implying we've already
15261580 // emitted a rewrite for the /_tree request), or if the route
15271581 // has PPR enabled and client param parsing is enabled, then
0 commit comments