ReviewOS

stacks/stx

SPA router: hard-reload on build-version skew between loaded runtime and fetched fragment

#1772
Closed glennmichael123 opened this 10 days ago ·
10 days ago

Problem

Under bun --watch, a loaded page holds the client runtime from build N. A file save restarts the server; the next SPA navigation fetches a fragment rendered by build N+1. Since served fragments legitimately carry preserved moustaches for client-side binding, any drift in the scoped-script/binding format between builds makes the OLD runtime fail to hydrate the NEW fragment — the swapped component renders its literal moustaches, dead x-shows, stale canvas. Sporadic + unreproducible-on-clean-boot, which is exactly its signature (observed repeatedly in ts-analytics dev while commits landed under a watching server; deep-dive traced the SPA path: fragment content itself is fine — packages/bun-plugin/src/serve.ts renders SPA requests through the same processDirectives and extracts the fragment post-render at :2294-2406).

Ask

Stamp a build/boot id on the page (e.g. window.__stxBuild, and an X-STX-Build header or meta on fragments). In the client router: if the fetched fragment's build id ≠ the loaded one, fall back to a full-page navigation instead of a DOM swap. Kills the whole skew class for ~20 lines, and matches what Next/Vite HMR clients do (full reload on version mismatch).

Deep-dive context: the static-vs-reactive moustache decision is currently implemented in ~7 sites across compile/build/bundle/runtime, each with its own heuristic — 8 regression fixes so far each patched a different layer (c571492, 4c5fb05, d411bf8, 409a2e0, bcd6f2c, 8ebb172, 20509da, da91c34). Consolidating that decision into one module consumed by all sites would end the whack-a-mole; the build-id reload above is the cheap immediate mitigation.

Sign in to comment on this issue.