Skip to content

fix(mock): version the worker script, so a new build replaces the old one - #1554

Merged
allanbowe merged 1 commit into
mainfrom
fix/mock-sw-version-stamp
Nov 5, 2026
Merged

allanbowe merged 1 commit into
mainfrom
fix/mock-sw-version-stamp

Conversation

@sasjs-dev

@sasjs-dev sasjs-dev Bot commented Nov 5, 2026

Copy link
Copy Markdown
Contributor

The mocked site installs a worker from a constant URL, so a browser that had cached sw.js kept running the previous build's worker - and through it the previous runtime. Both were reproduced on a published mock site today.

What it looks like

A site whose runtime had gained the webout() prelude handed a fresh drive to an old interpreter. Every mock service that calls webout() answered:

500 {"status":"failure","message":"Job execution failed.",
     "error":"ReferenceError: webout is not defined
              at eval (eval at runProgram (...runtime-core.js?v=6d2d56dbdc:1049:16), <anonymous>:23:1)"}

Opening the same program in a new window - or visiting the same deployment from a profile that had never seen it - worked, because those get the current worker. Clearing the origin's storage fixed it on the spot, which is what pointed at the worker rather than at the build or the service.

The host files are already cache-busted (?v=<hostVersion>, an md5 over runtime-core.js, persist.js, intercept.js, api-browser.js, webout-prelude.json), and the worker imports its runtime at that stamp - but the worker script itself is registered at /sw.js, so nothing makes the browser look at it again until its own revalidation cadence comes round.

The change

navigator.serviceWorker
  .register('/sw.js?v=' + version, { scope: '/', updateViaCache: 'none' })

A new build is a different script URL, so it installs and its skipWaiting() takes over immediately; updateViaCache: 'none' stops a reverse proxy from answering the update check with the previous copy. The version is the same hostVersion the rest of the loader already uses, so the two cannot disagree.

Verification

  • npx jest src/commands/build/internal/mockSite: 190 passing across the five suites; the extended assertion (register('/sw.js?v=, updateViaCache: 'none') fails if either half is dropped.
  • Prettier clean; npm run build clean.
  • Built the mocked DC estate with this CLI and served it: index.html carries register('/sw.js?v=5277c5d719', { scope: '/', updateViaCache: 'none' }), navigator.serviceWorker.controller.scriptURL is that URL, and a POST to services/usernav/usergroupsbymember answers 200 with the groups envelope.

One note for the same class of report: persist.js still skips re-seeding when IndexedDB already holds files, so a stale drive can outlive a stale worker. That is a separate question and I have not touched it here.

… one

The site cache-busts its host files with a version query, and the worker it
installs imports runtime-core.js at that stamp. The worker script itself was
registered from a constant URL, so a browser that had cached sw.js kept running
the previous build's worker - and through it the previous runtime. A site whose
runtime gained a capability then handed a fresh drive to an old interpreter: on
a published mock site whose runtime now defines webout(), every service that
calls it answered "Job execution failed." with "ReferenceError: webout is not
defined" until the visitor cleared site data. A private window, or the same
build served to a first-time visitor, worked.

Registering /sw.js?v=<hostVersion> makes a new build a different script, so the
worker installs and its skipWaiting takes over at once; updateViaCache: 'none'
keeps a reverse proxy from answering the update check with the previous copy.

Verified by building the mocked DC estate with this CLI: the emitted index.html
registers /sw.js?v=5277c5d719, the running controller reports that scriptURL,
and a POST to services/usernav/usergroupsbymember answers 200 with the groups
envelope. The new spec assertion fails if the stamp or updateViaCache is
dropped.
@allanbowe
allanbowe merged commit 37b2f0a into main Nov 5, 2026
10 checks passed
@allanbowe
allanbowe deleted the fix/mock-sw-version-stamp branch November 5, 2026 17:51
@github-actions

github-actions Bot commented Nov 5, 2026

Copy link
Copy Markdown

Coverage ratchet

Compared against the baseline published for the base commit 0f4a06f.

Metric Base Head Delta
statements 83.48% 83.48% 0 unchanged
branches 74.11% 74.11% 0 unchanged
functions 81.97% 81.97% 0 unchanged
lines 84.01% 84.01% 0 unchanged

No metric is below the base.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant