From 7c9563ec90e983631d1a30b4b5c6ede1cfd320d0 Mon Sep 17 00:00:00 2001 From: Eduard Wisch Date: Thu, 9 Apr 2026 01:26:26 +0200 Subject: [PATCH] =?UTF-8?q?feat:=20PWA=20Cache-Busting=20via=20filemtime?= =?UTF-8?q?=20(claude-db=20#201)=20=E2=80=94=20kein=20manuelles=20Hochz?= =?UTF-8?q?=C3=A4hlen=20mehr?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Das bisherige 'CACHE = baustelle-vN' Pattern erforderte, dass ich bei jeder Änderung drei Stellen synchron halte (sw.js, index.html ?v=, manifest). Eddy hat klargestellt dass das nicht akzeptabel ist. Fix nach KB #201 Pattern (referenz: dolibarr.stundenzettel v2.2.0): 1. index.html → index.php PHP berechnet bei jedem Request filemtime() von app.css, app.js, lib/*.js, manifest.webmanifest. Die mtimes kommen automatisch beim Deploy (rsync preserviert sie default) und werden als ?v= an alle Asset-URLs gehängt. 2. sw.js liest Version aus eigener URL-Query: const SW_VERSION = (new URL(self.location.href)).searchParams.get('v') const CACHE = 'baustelle-' + SW_VERSION activate() löscht alle caches die mit 'baustelle-' anfangen aber nicht der aktuelle sind. 3. Client-Registration mit Auto-Update: - setInterval 60s reg.update() - visibilitychange-Listener für Tab-Fokus - updatefound → SKIP_WAITING postMessage - controllerchange → einmaliger location.reload 4. SHELL pre-cache enthält nur statische Dateien (index.php, share.html, icons). CSS/JS werden beim ersten fetch dynamisch gecached — so gibt es keinen Mix zwischen alten und neuen ?v= Versionen. 5. manifest.webmanifest start_url auf /custom/baustelle/index.php Ergebnis: Ich deploye → mtime ändert sich → neue URLs → Browser holt frische Files → SW aktiviert automatisch beim nächsten Tab-Fokus. Nie wieder manuelles Hochzählen. Co-Authored-By: Claude Opus 4.6 (1M context) [deploy] --- index.html | 70 -------------------------------- index.php | 97 ++++++++++++++++++++++++++++++++++++++++++++ manifest.webmanifest | 2 +- sw.js | 23 +++++------ 4 files changed, 109 insertions(+), 83 deletions(-) delete mode 100644 index.html create mode 100644 index.php diff --git a/index.html b/index.html deleted file mode 100644 index 8b91e4d..0000000 --- a/index.html +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - - -Baustelle - - - - - - - - - -
-
- -

Baustelle

- - 🟢 -
- -
- - -
- -
- - - - - - - - - diff --git a/index.php b/index.php new file mode 100644 index 0000000..6b93b7b --- /dev/null +++ b/index.php @@ -0,0 +1,97 @@ + + + + + + + + + + +Baustelle + + + + + + + + + +
+
+ +

Baustelle

+ + 🟢 +
+ +
+ + +
+ +
+ + + + + + + + + diff --git a/manifest.webmanifest b/manifest.webmanifest index 2a01053..e2c4621 100644 --- a/manifest.webmanifest +++ b/manifest.webmanifest @@ -3,7 +3,7 @@ "short_name": "Baustelle", "description": "Mobile Doku für Baustellen — Fotos, Sprachnotizen, Skizzen", "id": "/custom/baustelle/", - "start_url": "/custom/baustelle/", + "start_url": "/custom/baustelle/index.php", "scope": "/custom/baustelle/", "display": "standalone", "orientation": "portrait", diff --git a/sw.js b/sw.js index 8a7f97e..0e1a421 100644 --- a/sw.js +++ b/sw.js @@ -1,25 +1,23 @@ -/* Baustelle PWA Service Worker — v9 - * Pattern nach claude-db #31: +/* Baustelle PWA Service Worker + * Pattern nach claude-db #201 (filemtime-basiert): + * - Cache-Version kommt aus URL-Query ?v=, kein manuelles Hochzählen * - Network-First für eigene Assets (immer aktuell, Fallback Cache) * - skipWaiting() + clients.claim() damit Updates sofort greifen * - Web Share Target via POST → share.html */ -const CACHE = 'baustelle-v10'; +// Cache-Version dynamisch aus ?v= — wird von index.php gesetzt +const SW_VERSION = (new URL(self.location.href)).searchParams.get('v') || 'static'; +const CACHE = 'baustelle-' + SW_VERSION; const SHELL = [ './', - './index.html', + './index.php', './share.html', - './app.css', - './app.js', - './manifest.webmanifest', - './lib/idb.js', - './lib/api.js', - './lib/offline.js', - './lib/router.js', './icons/icon-192.png', './icons/icon-512.png', './icons/icon.svg', + // CSS/JS werden mit ?v= geladen und dynamisch gecached + // beim ersten fetch — nicht in SHELL damit Pre-Cache nicht mit alten v's läuft ]; self.addEventListener('install', (e) => { @@ -34,7 +32,8 @@ self.addEventListener('activate', (e) => { e.waitUntil( caches.keys() .then(keys => Promise.all( - keys.filter(k => k !== CACHE).map(k => caches.delete(k)) + keys.filter(k => k.startsWith('baustelle-') && k !== CACHE) + .map(k => caches.delete(k)) )) .then(() => self.clients.claim()) );