Skip to content

revert(runner): keep the compiler chunk's content hash (DEV-2569) - #250

Merged
demtario merged 1 commit into
masterfrom
fix/DEV-2569-revert-stable-chunk-name
Aug 20, 2026
Merged

revert(runner): keep the compiler chunk's content hash (DEV-2569)#250
demtario merged 1 commit into
masterfrom
fix/DEV-2569-revert-stable-chunk-name

Conversation

@demtario

@demtario demtario commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Follow-up to #249, from the high-effort review of it. Reverts only the hash-free compiler chunk name. The shape fix — asBabel at both import sites, which is what DEV-2569's second pass was actually about — is untouched.

The chunk is not self-contained

Rollup hoists the shared CJS interop helpers into the entry, so the emitted compiler chunk opens with a static import of a content-hashed file. Verified against the live deploy of #249:

$ curl -s https://demos.handsontable.com/assets/compiler-babel.js | head -c 60
import{c as SD,g as Nke}from"./index-BpieVTaX.js";

$ curl -s https://demos.handsontable.com/ | grep -o 'src="/assets/[^"]*"'
src="/assets/index-BpieVTaX.js"

and that entry chunk's top level is createRoot(document.getElementById("root")).render(…) plus Sentry.init (main.tsx: "Must stay first: initialises error reporting before any other module runs").

So in the one scenario the rename existed to cure — a tab open across a deploy that then triggers its first Tier-1 compile — the stable path resolves against the new build, statically pulls a 1.3 MB entry chunk the tab has never loaded, and evaluates a second complete copy of the app. React 18 clears the root container on mount, so the visitor's workspace is detached and silently remounted from a different build: unsaved edits gone, no card, two Sentry clients, a second copy of every module singleton including a second babelLoader latch.

That is strictly worse than what it replaced. The carded failure it removed says "Restart the preview to try again, or reload the page — a tab left open across a deployment has to reload to pick up the current version" — actionable, and it does not throw away work. Not losing unsaved edits is the stated reason rearmCompilerLoad exists at all.

The mirror case has the same root cause: a cached stable compiler-babel.js against a newer page carries a static import of a rotated-out ./index-<oldhash>.js, so the SPA fallback answers 200 text/html and the original DEV-2569 failure is back — now reachable on a fresh load rather than only in a stale tab.

The hash is load-bearing: it is what makes a rotated chunk fail loudly instead of resolving against the wrong build. #249's new e2e could not have caught this — it exercises one build, where the compiler chunk and the entry agree by construction.

A stable path is still the right end state. It needs the compiler built as its own self-contained artifact (its own entry/bundle carrying its own interop helper), or the SPA fallback stopped from answering /assets/* so a rotated chunk returns a real 404 — not a chunkFileNames rename. Recorded in the vite config comment so it is not re-added, and a follow-up ticket will carry it.

The guard keeps its job, and closes two holes

scripts/check-compiler-chunk.mjs is rewritten around the hashed name. It still catches what it was written for — the manualChunks variant that pulled getDefaultExportFromCjs in and made the 2.3 MB chunk statically imported and modulepreloaded — and the same review found two gaps, both closed:

  • it now also matches a bare import"./babel-<hash>.js", the form Rollup emits when the importer uses none of the chunk's exports. That shape was eager while matching no from pattern and passing the dynamic-import count. Verified red by injecting one into a built chunk.
  • it prints the compiler chunk's own count of content-hashed dependencies — 1 hashed dependency/ies (index-<hash>.js) — must be 0 before it can be renamed. Reported rather than failed: it is the tripwire for when the rename becomes safe.

Still wired into ci.yml's authoring job and master.yml's deploy build.

Verification

result
pnpm test 847 pass / 0 fail / 2 todo
pnpm typecheck clean
node scripts/check-compiler-chunk.mjs ok: assets/babel-U33ShAoN.js, lazily imported by index-DASxLQnA.js only; 1 hashed dependency/ies
same, with a bare import injected red — imports babel-U33ShAoN.js statically — the chunk is no longer lazy
pnpm e2e e2e/preview-recovery.spec.ts 4 passed / 5 live-skipped

The e2e route glob goes back to **/assets/babel-*.js*. It is not vacuous after the change: the test asserts the recorded request list equals ["(bare)", "?hotRetry=1"] before Restart, which only holds if the route fired.

One review note recorded but not acted on here, since it predates both PRs: playwright.config.ts's webServer swallows --port/--strictPort (pnpm eats them), and with reuseExistingServer: !CI a local run can silently attach to another worktree's server on 4173 and test a stale build. It bit both the review and me; both runs above used an own-port preview instead.

🤖 Generated with Claude Code


Note

Cursor Bugbot is generating a summary for commit c1d64c9. Configure here.

Reverts the hash-free `assets/compiler-babel.js` from #249. The shape fix in
that PR — `asBabel` at both import sites — is untouched and is the fix the
ticket was about; this is only the second half, which a high-effort review
showed to be a net regression for the exact population it targeted.

The chunk is not self-contained. Rollup hoists the shared CJS interop helpers
into the entry, so the emitted compiler chunk opens with

  import { c as SD, g as Nke } from "./index-<hash>.js";

and that path is content-hashed. Verified on the deployed build (the merge of
#249 is live): `/assets/compiler-babel.js` begins
`import{c as SD,g as Nke}from"./index-BpieVTaX.js"`, index.html loads that same
hashed entry, and the entry's top level is
`createRoot(document.getElementById("root")).render(…)` plus Sentry.init.

So in the scenario the rename was meant to cure — a tab open across a deploy
that then triggers its first Tier-1 compile — the stable path resolves against
the *new* build, statically pulls a 1.3 MB entry the tab has never loaded, and
evaluates a second complete copy of the app. React 18 clears the root container
on mount, so the visitor's workspace is detached and silently remounted from a
different build: unsaved edits gone, no card, two Sentry clients. That is worse
than the carded failure it replaced, which tells the visitor to reload and is
what `describeRuntimeError` and `rearmCompilerLoad`'s docblock both promise. The
mirror case is the same root cause: a cached stable chunk against a newer page
has a static import of a rotated-out hashed path, i.e. the original DEV-2569
failure on a fresh load.

The hash is therefore load-bearing: it is what makes a rotated chunk fail
loudly. A stable path is still the right end state, but it needs the compiler
built as its own self-contained artifact — or the SPA fallback stopped from
answering /assets/* — rather than a `chunkFileNames` rename. Recorded in the
config comment so it is not re-added, and a follow-up will carry the real fix.

`check-compiler-chunk.mjs` is rewritten around the hashed name and keeps its
reason for existing (the `manualChunks` variant that made the chunk eager is
still red). Two gaps the same review found are closed: it now also matches a
bare `import"./babel-<hash>.js"` — the form Rollup emits when the importer uses
none of the chunk's exports, which was eager while matching no `from` pattern
(verified red by injecting one) — and it prints the chunk's own count of
content-hashed dependencies, the number that has to reach zero before a rename
is safe. It stays wired into ci.yml and master.yml.

Verified: pnpm test 847 pass / 0 fail, typecheck clean, guard green on the
build and red on an injected bare import, preview-recovery.spec.ts 4 passed /
5 live-skipped against the rebuilt app.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@demtario demtario self-assigned this Aug 20, 2026
@demtario
demtario merged commit 321dd16 into master Aug 20, 2026
7 checks passed
@demtario
demtario deleted the fix/DEV-2569-revert-stable-chunk-name branch August 20, 2026 14:54
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