Split frontend/app.js into ES modules #25

Open
opened 2026-08-30 21:31:06 +02:00 by kristofferopsahl · 1 comment
Collaborator

Child of #7.

Rebuild the asset-version guard to cover the module graph first, then split state/rendering by surface using browser-loaded ES modules.

Acceptance: existing render and asset-version characterization tests pass without re-baselining; no surface depends on implicit global ordering.

Child of #7. Rebuild the asset-version guard to cover the module graph first, then split state/rendering by surface using browser-loaded ES modules. Acceptance: existing render and asset-version characterization tests pass without re-baselining; no surface depends on implicit global ordering.
Owner

Evidence for the "rebuild the guard first" ordering, from tonight rather than in principle.

test_asset_version.py caught a real break on main a few minutes after #21 merged. frontend/index.html served ?v=134 while the four assets hashed to d20d1fa11d2d9a94 against a recorded a932c205c61efb9b — the frontend changed again in 4089295 after the version was last set. A browser holding 134 would have been served the old JS against the new markup, which is precisely the failure the guard exists to catch, and it is invisible without it: nothing else in the suite compares what is on disk to what is advertised.

Fixed mechanically in 1c94db7 (bump to 135, record the digest the files actually hash to), following the ritual written into the test itself. Main is green again.

Found by running the full suite on the merged result — worth noting that neither side had, since #19, #20 and #21 were each green alone.

Why this bears on the ordering here. The guard currently works because there are exactly four files and one version string. Splitting app.js into a module graph breaks both halves of that assumption at once: the digest must cover every module, and ?v= on the entry point no longer invalidates a changed leaf. If the guard is rebuilt after the split, there is a window where the assets can drift from what is advertised and nothing says so — and tonight is a concrete example of that drift happening within minutes of an unrelated merge.

So the ordering in this issue is right, and the acceptance criterion should probably be sharper than "existing tests pass": the rebuilt guard must fail when any single module changes without the version moving. That is a prove-RED on the new guard, not a green run of the old one — the old one cannot fail once the file it watches no longer exists.

Evidence for the "rebuild the guard first" ordering, from tonight rather than in principle. **`test_asset_version.py` caught a real break on main a few minutes after #21 merged.** `frontend/index.html` served `?v=134` while the four assets hashed to `d20d1fa11d2d9a94` against a recorded `a932c205c61efb9b` — the frontend changed again in `4089295` after the version was last set. A browser holding `134` would have been served the old JS against the new markup, which is precisely the failure the guard exists to catch, and it is invisible without it: nothing else in the suite compares what is on disk to what is advertised. Fixed mechanically in `1c94db7` (bump to 135, record the digest the files actually hash to), following the ritual written into the test itself. Main is green again. Found by running the full suite on the merged result — worth noting that neither side had, since #19, #20 and #21 were each green alone. **Why this bears on the ordering here.** The guard currently works because there are exactly four files and one version string. Splitting `app.js` into a module graph breaks both halves of that assumption at once: the digest must cover every module, and `?v=` on the entry point no longer invalidates a changed leaf. If the guard is rebuilt *after* the split, there is a window where the assets can drift from what is advertised and nothing says so — and tonight is a concrete example of that drift happening within minutes of an unrelated merge. So the ordering in this issue is right, and the acceptance criterion should probably be sharper than "existing tests pass": **the rebuilt guard must fail when any single module changes without the version moving.** That is a prove-RED on the new guard, not a green run of the old one — the old one cannot fail once the file it watches no longer exists.
Sign in to join this conversation.
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
solvreven/FPL#25
No description provided.