From c802c43e040f5aef5755edc5e4eb33dcdc939da1 Mon Sep 17 00:00:00 2001 From: 3dtours Date: Fri, 2 Oct 2026 20:10:02 +0700 Subject: [PATCH] fix(assets): give the frame sheets a build-stamped URL, so a replaced sheet stops arriving from cache --- docker/frontend/src/engine/assets.ts | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/docker/frontend/src/engine/assets.ts b/docker/frontend/src/engine/assets.ts index 483ee78..49c3ab7 100644 --- a/docker/frontend/src/engine/assets.ts +++ b/docker/frontend/src/engine/assets.ts @@ -18,6 +18,16 @@ export const MARK_FACES: { family: string; file: string }[] = [ { family: 'Fraunces', file: '/assets/Fraunces-Regular.ttf' }, ]; +// The two frame sheets are drawn by hand and dropped over the file of the same +// name, and that name is the one thing neither cache lets go of: nginx answers +// /assets/ immutable for 30 days (nginx.conf) and the service worker serves the +// path cache-first (sw.js) — both stored for the sheet that was there the day the +// visitor first loaded the app, so a sheet swapped in today arrives as yesterday's. +// The build stamp in the query is what makes the URL move with the build; the old +// entry stays in both caches, unasked for, and ages out on its own. +const ART = `?v=${import.meta.env.VITE_VERSION ?? ''}`; + +// The fonts never change under a build, so they keep the plain URL. async function buf(url: string): Promise { const res = await fetch(url); if (!res.ok) throw new Error(`fetch ${url}: ${res.status}`); @@ -37,8 +47,8 @@ export async function loadEngine(): Promise<{ assets: RenderAssets; gpu: boolean const [textFont, emojiFont, wallframePng, oldFilmPng, markFonts] = await Promise.all([ buf('/assets/Cousine-Regular.ttf'), buf('/assets/NotoEmoji-GPS.ttf'), - buf('/assets/wallframe.png'), - buf('/assets/old_film.png'), + buf(`/assets/wallframe.png${ART}`), + buf(`/assets/old_film.png${ART}`), Promise.all(MARK_FACES.map(async (face) => ({ family: face.family, bytes: await buf(face.file) }))), ]); assets = {