@@ -4,7 +4,12 @@ import {
44 type RouteCacheabilityOutcome ,
55 type RouteCacheabilityState ,
66} from "vinext/shims/cacheability-classification" ;
7- import { applyCdnResponseHeaders , NO_STORE_CACHE_CONTROL } from "./cache-control.js" ;
7+ import {
8+ applyCdnResponseHeaders ,
9+ hasExplicitNonCacheableResponsePolicy ,
10+ NO_STORE_CACHE_CONTROL ,
11+ } from "./cache-control.js" ;
12+ import { isNonCacheableCacheControl } from "vinext/shims/cdn-cache" ;
813import { VINEXT_CACHEABILITY_PROBE_HEADER , VINEXT_PRERENDER_SECRET_HEADER } from "./headers.js" ;
914import { workerCapabilityMatches } from "./worker-prerender-discovery.js" ;
1015import {
@@ -27,7 +32,7 @@ type CacheabilityProbeRouteState =
2732
2833type CacheabilityProbeResult = {
2934 cacheControl ?: string ;
30- kind ?: "app-page" ;
35+ kind ?: "app-page" | "pages-page" ;
3136 pattern ?: string ;
3237 reason ?: string ;
3338 state : CacheabilityProbeRouteState ;
@@ -285,6 +290,38 @@ function responseWithCachePolicy(
285290 } ) ;
286291}
287292
293+ function inferPagesPageCacheability ( response : Response ) : RouteCacheabilityOutcome {
294+ const cacheControl =
295+ response . headers . get ( "Cloudflare-CDN-Cache-Control" ) ??
296+ response . headers . get ( "CDN-Cache-Control" ) ??
297+ response . headers . get ( "Cache-Control" ) ;
298+ if ( ! cacheControl || isNonCacheableCacheControl ( cacheControl ) ) {
299+ return { cacheable : false } ;
300+ }
301+ const cacheTag = response . headers . get ( "Cache-Tag" ) ;
302+ return {
303+ cacheable : true ,
304+ cacheControl,
305+ ...( cacheTag
306+ ? {
307+ tags : cacheTag
308+ . split ( "," )
309+ . map ( ( tag ) => tag . trim ( ) )
310+ . filter ( Boolean ) ,
311+ }
312+ : { } ) ,
313+ } ;
314+ }
315+
316+ function completedRouteOutcome (
317+ response : Response ,
318+ state : RouteCacheabilityState ,
319+ ) : RouteCacheabilityOutcome | null {
320+ if ( state . route ?. kind !== "pages-page" ) return state . outcome ?? null ;
321+ if ( hasExplicitNonCacheableResponsePolicy ( response . headers ) ) return { cacheable : false } ;
322+ return state . outcome ?? inferPagesPageCacheability ( response ) ;
323+ }
324+
288325function staticToDynamicResponse ( route : CacheabilityManifestRoute ) : Response {
289326 const headers = new Headers ( { "Content-Type" : "text/plain; charset=utf-8" } ) ;
290327 applyCdnResponseHeaders ( headers , { cacheControl : NO_STORE_CACHE_CONTROL } ) ;
@@ -312,12 +349,17 @@ async function finalizeWorkerCacheabilityAdmission(
312349 return responseWithCachePolicy ( response , response . body , null ) ;
313350 }
314351 const manifest = admission . manifest as CacheabilityManifest ;
315- const manifestRoute = findCacheabilityManifestRoute ( manifest , state . route . pattern , {
316- representation : admission . representation as Parameters <
317- typeof findCacheabilityManifestRoute
318- > [ 2 ] [ "representation" ] ,
319- requestKey : admission . requestKey ,
320- } ) ;
352+ const manifestRoute = findCacheabilityManifestRoute (
353+ manifest ,
354+ state . route . kind ,
355+ state . route . pattern ,
356+ {
357+ representation : admission . representation as Parameters <
358+ typeof findCacheabilityManifestRoute
359+ > [ 3 ] [ "representation" ] ,
360+ requestKey : admission . requestKey ,
361+ } ,
362+ ) ;
321363 if (
322364 ! manifestRoute ||
323365 manifestRoute . state === "dynamic" ||
@@ -338,7 +380,9 @@ async function finalizeWorkerCacheabilityAdmission(
338380 return responseWithCachePolicy ( response , captured . body , null ) ;
339381 }
340382
341- const outcome = state . completion ? await state . completion : ( state . outcome ?? null ) ;
383+ const outcome = state . completion
384+ ? await state . completion
385+ : completedRouteOutcome ( response , state ) ;
342386 if ( outcome ?. cacheable !== true || ! outcome . cacheControl ) {
343387 return manifestRoute . state === "static-candidate" &&
344388 ( outcome === null || outcome . dynamicUsage === true )
@@ -366,7 +410,7 @@ export async function finalizeWorkerCacheabilityResponse(
366410 state . route ? "runtime-check" : "probe-failed" ,
367411 state . route
368412 ? { cacheable : false }
369- : { cacheable : false , reason : "request did not resolve to a probeable App Page " } ,
413+ : { cacheable : false , reason : "request did not resolve to a probeable page route " } ,
370414 response . status ,
371415 ) ;
372416 }
@@ -376,7 +420,7 @@ export async function finalizeWorkerCacheabilityResponse(
376420 return probeResponse (
377421 state ,
378422 "probe-failed" ,
379- { cacheable : false , reason : "request did not resolve to a probeable App Page " } ,
423+ { cacheable : false , reason : "request did not resolve to a probeable page route " } ,
380424 response . status ,
381425 ) ;
382426 }
@@ -401,7 +445,9 @@ export async function finalizeWorkerCacheabilityResponse(
401445 ) ;
402446 }
403447
404- const outcome = state . completion ? await state . completion : state . outcome ;
448+ const outcome = state . completion
449+ ? await state . completion
450+ : completedRouteOutcome ( response , state ) ;
405451 if ( ! outcome ) {
406452 return probeResponse (
407453 state ,
0 commit comments