Skip to content

PWA serves stale frontend after deploy (footer shows new version, code is old) until hard refresh #55

Description

@szrudi

Symptom

After a new version is deployed, an already-open session keeps running the
old frontend bundle while the footer shows the new version number — so
the UI looks updated but behaves like the old code until a manual hard
refresh
. This has twice caused false "the fix doesn't work" reports during
testing (most recently the #52 variable-rename fix, which was actually fine —
the tab was running cached pre-1.8.3 JS).

The mismatch is the giveaway: the footer reads the live server /api/health
(client/src/components/Footer.tsx), which returns the new version instantly,
while the running JS/HTML come from the service-worker precache and don't swap
until the page reloads.

Why it happens

  • The PWA already uses registerType: "autoUpdate" (client/vite.config.ts:22)
    with generateSW. The app shell + hashed JS are precached (cache-first);
    only /api/* is NetworkFirst.
  • autoUpdate updates the service worker in the background, but an already-open
    tab/PWA keeps its loaded assets
    — the new SW typically takes control on the
    next navigation, not the current page. There's no explicit registration in
    client/src (grep for registerSW/virtual:pwa is empty), so we rely on the
    default injected registration and never force a reload on update.

Net: deploy → SW fetches new precache in the background → open session still runs
old code until the user happens to fully reload.

Options to fix

  1. Auto-reload on update (best for a kiosk-style household printer): register
    via virtual:pwa-register and reload the page when the new SW activates
    (listen for controllerchange / use the autoUpdate callback), so an open tab
    refreshes itself shortly after a deploy.
  2. Reload prompt: use onNeedRefresh to show a small "New version available —
    reload" toast, letting the user choose. Less surprising than an auto-reload.
  3. Version-mismatch guard (belt-and-suspenders, directly kills the confusing
    symptom):
    compare the build-time __APP_VERSION__ (already injected, see
    vite.config.ts:17) against /api/health's version in Footer/app init;
    if they differ, surface the reload prompt. Guarantees footer-version and
    running-code can never silently disagree.

Suggest 1 or 3 (or both). Mostly a client/vite.config.ts + a small SW-registration
module change; low risk.

Impact

Not a user-data bug, but it repeatedly masks real fixes during testing and would
confuse end users after an update. Worth doing before the next round of
user-facing changes.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions