feat(frontend): finish PWA reset reload and pre-cache the HTML shell
The service worker and web manifest were already in place; close the remaining
gaps against the PWA spec:
- pwa.ts: resetPwa() cleared caches and unregistered the service worker but
never reloaded, despite its docstring. Add the hard reload so the page
re-fetches everything from the network after a clear.
- service-worker.ts: pre-cache the SPA entry HTML ('/') alongside build/files
so the shell — and the offline navigation fallback — works from the very
first visit, not just after a navigation has been seen by the runtime cache.
- settings: resetPwa now reloads, so the post-clear success toast (which told
the user to reload manually) is unreachable and misleading. Drop the dead
pwaSuccess state and toast; keep the disabled "Clearing…" button state.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -11,4 +11,7 @@ export async function resetPwa(): Promise<void> {
|
|||||||
const keys = await caches.keys();
|
const keys = await caches.keys();
|
||||||
await Promise.all(keys.map((k) => caches.delete(k)));
|
await Promise.all(keys.map((k) => caches.delete(k)));
|
||||||
}
|
}
|
||||||
|
// Hard reload so the page (and a fresh service worker, if still installed)
|
||||||
|
// re-fetches everything from the network instead of the now-cleared cache.
|
||||||
|
location.reload();
|
||||||
}
|
}
|
||||||
@@ -85,16 +85,15 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
// ---- PWA reset ----
|
// ---- PWA reset ----
|
||||||
|
// doPwaReset() clears the caches/SW and then hard-reloads the page, so there's
|
||||||
|
// no post-success state to surface here — just keep the button disabled while it
|
||||||
|
// runs until the reload takes over.
|
||||||
let pwaResetting = $state(false);
|
let pwaResetting = $state(false);
|
||||||
let pwaSuccess = $state(false);
|
|
||||||
|
|
||||||
async function resetPwa() {
|
async function resetPwa() {
|
||||||
pwaResetting = true;
|
pwaResetting = true;
|
||||||
pwaSuccess = false;
|
|
||||||
try {
|
try {
|
||||||
await doPwaReset();
|
await doPwaReset();
|
||||||
pwaSuccess = true;
|
|
||||||
setTimeout(() => (pwaSuccess = false), 3000);
|
|
||||||
} finally {
|
} finally {
|
||||||
pwaResetting = false;
|
pwaResetting = false;
|
||||||
}
|
}
|
||||||
@@ -226,10 +225,7 @@
|
|||||||
<!-- ====== PWA ====== -->
|
<!-- ====== PWA ====== -->
|
||||||
<section class="card">
|
<section class="card">
|
||||||
<h2 class="section-title">App cache</h2>
|
<h2 class="section-title">App cache</h2>
|
||||||
<p class="hint-text">Clear service worker and cached assets. Useful if the app feels stale after an update.</p>
|
<p class="hint-text">Clear service worker and cached assets, then reload. Useful if the app feels stale after an update.</p>
|
||||||
{#if pwaSuccess}
|
|
||||||
<p class="msg success" role="status">Cache cleared. Reload the page to fetch fresh assets.</p>
|
|
||||||
{/if}
|
|
||||||
<div class="row-actions">
|
<div class="row-actions">
|
||||||
<button class="btn danger-outline" onclick={resetPwa} disabled={pwaResetting}>
|
<button class="btn danger-outline" onclick={resetPwa} disabled={pwaResetting}>
|
||||||
{pwaResetting ? 'Clearing…' : 'Clear PWA cache'}
|
{pwaResetting ? 'Clearing…' : 'Clear PWA cache'}
|
||||||
|
|||||||
@@ -8,8 +8,11 @@ declare const self: ServiceWorkerGlobalScope;
|
|||||||
// Cache name is versioned so a new deploy invalidates the old shell.
|
// Cache name is versioned so a new deploy invalidates the old shell.
|
||||||
const CACHE = `app-shell-${version}`;
|
const CACHE = `app-shell-${version}`;
|
||||||
|
|
||||||
// App shell: all Vite-emitted JS/CSS chunks + static assets (fonts, icons, manifest).
|
// App shell: the SPA entry HTML ('/'), all Vite-emitted JS/CSS chunks, and the
|
||||||
const SHELL = [...build, ...files];
|
// static assets (fonts, icons, manifest). Pre-caching '/' makes the shell — and
|
||||||
|
// therefore the whole offline fallback below — available from the very first
|
||||||
|
// visit, before any navigation has been seen by the runtime cache.
|
||||||
|
const SHELL = ['/', ...build, ...files];
|
||||||
|
|
||||||
// ---- Install: pre-cache the app shell ----
|
// ---- Install: pre-cache the app shell ----
|
||||||
self.addEventListener('install', (event) => {
|
self.addEventListener('install', (event) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user