From bbae95b504bfae3ef6a04311315893141858c311 Mon Sep 17 00:00:00 2001 From: librelad Date: Tue, 26 May 2026 22:55:35 +0100 Subject: [PATCH] fix(webui): drop static-asset cache from 1h to 60s MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The 1h max-age set in Phase A caused a cache-vs-deploy mismatch when Phase B refactored config-manager.js to lazy-load admin-overview.js et al. The new index.html no longer eager-loads those scripts, but browsers with the cached (pre-Phase-B) config-manager.js didn't do the lazy-load either — so AdminOverview / AdminSystem / etc. were undefined and the admin tools rendered 'failed to load' errors. 60s is the right balance: rapid in-session clicks skip the network round-trip, but a deploy is visible within a minute. ETag-based 304s still keep the per-request cost tiny when nothing changed. Signed-off-by: librelad --- containers/libreportal/backend/utils/middleware.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/containers/libreportal/backend/utils/middleware.js b/containers/libreportal/backend/utils/middleware.js index 350891e..fbec379 100755 --- a/containers/libreportal/backend/utils/middleware.js +++ b/containers/libreportal/backend/utils/middleware.js @@ -30,14 +30,16 @@ function noStore(req, res, next) { } // Static-asset options: -// - 1h maxAge + ETag on JS/CSS/icons so repeated nav skips a network -// round-trip per file. ~25 script tags × ~5ms RTT each adds up otherwise. -// - HTML files get Cache-Control: no-cache (still uses ETag, so revalidation -// is cheap, but new deploys land immediately without waiting for cache -// expiry — the SPA shell is the file most likely to change between deploys). +// - 60s maxAge + ETag on JS/CSS/icons. Long enough that rapid in-session +// clicks skip the network round-trip, short enough that a deploy is +// visible within a minute. Originally tried 1h but that caused stale +// cached JS to reference things the new HTML no longer loaded (the +// Phase-B lazy-load refactor changed who loads which script). +// - HTML files get Cache-Control: no-cache (always revalidates via ETag, +// so new deploys land immediately — the SPA shell changes most often). // - dotfiles='ignore' so .auth.json is never served. const staticOptions = { - maxAge: '1h', + maxAge: '60s', etag: true, dotfiles: 'ignore', setHeaders: (res, filePath) => {