From dc2eb37ec26310307fd94ef2cb5c6e5c4068c88e Mon Sep 17 00:00:00 2001 From: Gavyn Caldwell Date: Fri, 13 Mar 2026 10:27:53 -0600 Subject: [PATCH] use Cloudflare Cache API for actual edge caching MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit s-maxage headers alone do nothing on Workers — responses bypass Cloudflare's HTTP cache by default. Now explicitly storing responses in edge cache via caches.default, same pattern as icon proxy. Covers all page routes, sitemaps, and robots.txt. --- src/routes/-worker-entry.ts | 47 +++++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 15 deletions(-) diff --git a/src/routes/-worker-entry.ts b/src/routes/-worker-entry.ts index a498d62..bedd741 100644 --- a/src/routes/-worker-entry.ts +++ b/src/routes/-worker-entry.ts @@ -309,20 +309,25 @@ async function handleIconProxy(request: Request): Promise { // ─── Worker Entry ─────────────────────────────────────────────────── +const cache = (caches as unknown as { default: Cache }).default; + export default { async fetch(request: Request, _env: Env): Promise { const url = new URL(request.url); const { pathname } = url; - // robots.txt - if (pathname === "/robots.txt") { - return robotsTxt(); - } - - // Sitemaps - const sitemapHandler = sitemapHandlers[pathname]; - if (sitemapHandler) { - return sitemapHandler(); + // robots.txt + sitemaps — serve from edge cache + if (pathname === "/robots.txt" || sitemapHandlers[pathname]) { + const cacheKey = new Request(url.toString(), { method: "GET" }); + const cached = await cache.match(cacheKey); + if (cached) return cached; + + const response = + pathname === "/robots.txt" + ? robotsTxt() + : await sitemapHandlers[pathname](); + cache.put(cacheKey, response.clone()).catch(() => {}); + return response; } // Icon proxy @@ -330,15 +335,27 @@ export default { return handleIconProxy(request); } + // Determine if this route is cacheable + const cacheHeader = getCacheHeader(pathname); + + // Check edge cache for cacheable GET requests + if (cacheHeader && request.method === "GET") { + const cacheKey = new Request(url.toString(), { method: "GET" }); + const cached = await cache.match(cacheKey); + if (cached) return cached; + } + // Pass through to TanStack Start const response = await tanstackFetch(request); - // Apply cache headers - const cacheHeader = getCacheHeader(pathname); - if (cacheHeader && response.status === 200) { - const newResponse = new Response(response.body, response); - newResponse.headers.set("Cache-Control", cacheHeader); - return newResponse; + // Store cacheable responses in edge cache + if (cacheHeader && response.status === 200 && request.method === "GET") { + const cacheKey = new Request(url.toString(), { method: "GET" }); + const cacheable = new Response(response.body, response); + cacheable.headers.set("Cache-Control", cacheHeader); + // Fire-and-forget cache write + cache.put(cacheKey, cacheable.clone()).catch(() => {}); + return cacheable; } return response;