From 27aadd113961d6f66e6a3ac7df161e3d1bbf7d80 Mon Sep 17 00:00:00 2001 From: Burak Yigit Kaya Date: Sat, 16 May 2026 18:24:39 +0000 Subject: [PATCH] fix(server): add Cache-Control headers to static assets Hashed assets (Vite content-hashed filenames) get immutable/1yr cache. HTML gets no-cache to always revalidate for fresh asset references. Other static files (favicons, manifest) get 1hr cache. --- packages/opencode/src/server/shared/ui.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/packages/opencode/src/server/shared/ui.ts b/packages/opencode/src/server/shared/ui.ts index fd4c73188063..6345579b594f 100644 --- a/packages/opencode/src/server/shared/ui.ts +++ b/packages/opencode/src/server/shared/ui.ts @@ -52,9 +52,18 @@ function notFound() { return HttpServerResponse.jsonUnsafe({ error: "Not Found" }, { status: 404 }) } +// Vite content-hashed filenames contain a hash segment (e.g. index-abc123.js) +const HASHED_ASSET_REGEX = /[-.][\da-f]{8,}\.\w+$/ + +function cacheControl(file: string) { + if (AppFileSystem.mimeType(file).startsWith("text/html")) return "no-cache" + if (HASHED_ASSET_REGEX.test(file)) return "public, max-age=31536000, immutable" + return "public, max-age=3600" +} + function embeddedUIResponse(file: string, body: Uint8Array) { const mime = AppFileSystem.mimeType(file) - const headers = new Headers({ "content-type": mime }) + const headers = new Headers({ "content-type": mime, "cache-control": cacheControl(file) }) if (mime.startsWith("text/html")) { headers.set("content-security-policy", cspForHtml(new TextDecoder().decode(body))) }