/** cloudflare paints every `_headers` rule onto the response for a matching * path, including the empty 404 its asset server answers when a hashed file is * missing. the adapter's autogenerated `immutable, max-age=31536000` therefore * pins that 404 in the reader's browser for a year: an asset requested a moment * before its deploy finished landing leaves that browser with an unstyled page * and a code view that never mounts, and no refresh clears it - the cache * answers before the network does. * * the bytes behind a hashed url are immutable, but its existence is * deploy-scoped, so the rule that survives is one the browser revalidates: * a stale entry still paints instantly, and the revalidation behind it turns a * poisoned 404 back into the asset. */ export const REVALIDATED_IMMUTABLE = "public, max-age=60, stale-while-revalidate=31536000"; const rule = (appDir: string) => `/${appDir}/immutable/*\n ! Cache-Control\n Cache-Control: ${REVALIDATED_IMMUTABLE}`; /** cloudflare applies later rules over earlier ones, so this lands after the * adapter's autogenerated block rather than replacing it */ export const hardenAssetHeaders = (headers: string, appDir = "_app"): string => headers.includes(REVALIDATED_IMMUTABLE) ? headers : `${headers.trimEnd()}\n\n# a hashed url's bytes never change, but its existence is deploy-scoped:\n# revalidation is what lets a 404 cached during a deploy heal itself\n${rule(appDir)}\n`;