GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | ||||||||||||||||||||||||||||||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | ||||||||||||||||||||||||||||||
GeezerVison is showing github.com — fix(@angular/build): disable code splitting for unit test builds by jonmarozick · Pull Request #33729 · angular/angular-cli Conversation
|
| output files | total size | chunks | wall | |
|---|---|---|---|---|
| splitting on | 169 | 1.21 MB | 57 | 30s |
| splitting off | 112 | 6.93 MB | 0 | 28s |
Total output grows ~5.7×; test run time was unchanged. If the extra memory is a concern for very
large suites, gating the option on the runner being jsdom (rather than all Vitest builds) would
narrow it, since browser mode does not exhibit the bug — happy to adjust.
Verification. Verified by applying the equivalent change to an installed 21.2.19
@angular/build (building the CLI from source with Bazel was not available on this machine), so CI
should be treated as the authoritative run:
| check | before | after |
|---|---|---|
| minimal reproduction (jsdom) | 1 failed / 1 passed | 2 passed |
| real 105-spec-file project, browser mode | 1018 passed | 1018 passed |
ng build (application build, flag unset) |
ok | ok, still splits |
Regression test. unit-test/tests/behavior/vitest-shared-chunk-init_spec.ts encodes the
issue's four trigger conditions: a shared const imported by two spec entries (shared chunk), a
component reading it in a class-field initializer, an async test callback in that component's
spec (no await needed), and zone.js in the polyfills (the setupApplicationTarget default).
Earlier fixture attempts passed without the fix because their test callbacks were synchronous —
zone forces async downleveling, the spec then imports the __async helper, and esbuild emits that
spec entry CommonJS-wrapped with the component module behind a lazy __esm initializer, which is
the shape in which the cross-chunk read fails.
Since Bazel wasn't runnable on my machine, the fixture's exact file contents were validated
against an installed 21.2.19 @angular/build in a fresh ng new workspace: unpatched, the
container spec fails with the issue's TypeError (1 failed / 2 passed); with this change
applied, all pass and no chunk-*.js is emitted. Please treat the CI run of the harness test as
authoritative. One caveat encoded as a comment in the test: the failure is sensitive to inert
content (a top-level console.log in either module defuses it), so the fixtures intentionally
mirror the reproduction byte-for-byte rather than a paraphrase.
🤖 Generated with Claude Code
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
b8a3e00 to
9e99820
Compare
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
This pull request introduces a new internal option, disableCodeSplitting, to the application builder options. This option is designed to disable esbuild code splitting for browser code bundles, which is particularly useful for unit-test runners (such as Vitest) where module loading does not reliably preserve live ESM bindings across chunk boundaries. The option has been integrated into the option normalization process, the Vitest build options, and the browser code bundle creation logic. I have no feedback to provide as there are no review comments to address.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
Every spec file is its own entry point, so esbuild code splitting hoists any module reached from more than one spec into a chunk shared between them. A module placed in a shared chunk is wrapped in a lazy `__esm` initializer, so its exported value is only assigned once that initializer runs, and importing chunks read the export as a live ESM binding. The unit test runners load the generated output through a module runner rather than the browser's own ESM implementation, and that does not reliably preserve those bindings. An importing chunk can therefore observe the export as `undefined`. A component whose class field initializer reads a `const` exported from a module that was hoisted into a shared chunk fails with a `TypeError`, while the same value read later, or read from within the shared chunk itself, is correct. It only appears once a project has more than one spec file, because a single entry point inlines everything and never splits. Test bundles are never downloaded by a browser, so splitting has nothing to optimize here. This disables it for the unit test build only, via an internal option, leaving application builds unaffected. The regression test mirrors the reproduction's exact shape: a shared const read during class-field initialization from a spec with an async test callback, under zone.js polyfills. That combination is load-bearing: zone.js downlevels async, the spec then imports the `__async` helper, and esbuild emits the spec entry CommonJS-wrapped with the component module behind a lazy `__esm` initializer. The fixture file set was verified to fail against an unpatched 21.2.19 build and pass with this change applied.
9e99820 to
746b351
Compare
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the contribution.
This appears to be the cleanest approach to ensure resilience with Vitest's synthetic module runner.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
|
This PR was merged into the repository. The changes were merged into the following branches: |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
This pull request has been automatically locked due to inactivity. Read more about our automatic conversation locking policy. This action has been performed automatically by a bot. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
Successfully merging this pull request may close these issues.
@angular/build:unit-test: with the default jsdom runner and zone.js, an export from a shared chunk is undefined when read during class-field initialisation from a spec with an async test
There was an error while loading. Please reload this page.