Skip to content

fix(angular-rspack): keep class field closures per instance in minified builds - #37066

Open
leosvelperez wants to merge 2 commits into
masterfrom
gh-37050
Open

leosvelperez wants to merge 2 commits into
masterfrom
gh-37050

Conversation

@leosvelperez

@leosvelperez leosvelperez commented Sep 16, 2026

Copy link
Copy Markdown
Member

Current Behavior

Production builds from @nx/angular-rspack and @nx/rspack can break classes whose field initializers pass a callback to a helper. Every instance ends up calling the callback of the last instance created.

function wrap(cb) { return () => cb(); }
class C { static n = 0; id = ++C.n; v = wrap(() => this.id); }
[new C(), new C(), new C()].map((c) => c.v()); // unminified: 1,2,3; minified: 3,3,3

The SWC minifier inlines the helper and assigns the callback to a variable that all instances share. In Angular apps this breaks injectVirtualizer from @tanstack/angular-virtual when a page has more than one virtual list. In @nx/rspack apps, the default swc-loader rule compiles app code down to ES5, so there the bug hits dependencies that ship native class fields.

Expected Behavior

Each instance keeps its own callback in minified production builds, for browser and server builds.

Related Issue(s)

Fixes #37050

Implementation Notes

  • Both minimizers set compress: { inline: 0, reduce_funcs: false }. Either flag alone still miscompiles. Rspack keeps adding passes: 2 to the object.
  • On a larger Angular Material app, gzip size went down 0.12% and raw size went up 0.43%. Build time stayed within noise.
  • Other minimizers: Terser fixes it too, but production builds took 1.9x as long. The esbuild output grew 116%, because its transform keeps unused code inside Rspack's module functions. The oxc-minify package is labeled alpha and has open miscompile reports.
  • Other settings: compress: false grows raw output 167% to 176%, and concatenateModules: false misses helpers in the same file. Swapping reduce_funcs: false for reduce_vars: false works but adds 1.8% gzip.
  • The defect is in the SWC minifier, reported upstream as es/minifier: class field callback shared across instances after helper inlining swc-project/swc#12380. It reproduces on rspack 1.3.5, 1.6.8, 2.0.4 and 2.2.4, and on @swc/core 1.16.2 and the latest nightly. The options can go once an rspack release ships the fix.
  • Not covered: @nx/rspack projects whose composePlugins config replaces optimization.minimizer, such as the generated Nest config.

View Polygraph session ↗

@netlify

netlify Bot commented Sep 16, 2026

Copy link
Copy Markdown

Deploy Preview for nx-docs ready!

Name Link
🔨 Latest commit a157506
🔍 Latest deploy log https://app.netlify.com/projects/nx-docs/deploys/6aaa50136a7e32000892204e
😎 Deploy Preview https://deploy-preview-37066--nx-docs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@netlify

netlify Bot commented Sep 16, 2026

Copy link
Copy Markdown

Deploy Preview for nx-dev ready!

Name Link
🔨 Latest commit a157506
🔍 Latest deploy log https://app.netlify.com/projects/nx-dev/deploys/6aaa5013fa97690008ddf0b2
😎 Deploy Preview https://deploy-preview-37066--nx-dev.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@leosvelperez leosvelperez self-assigned this Sep 16, 2026
@nx-cloud

nx-cloud Bot commented Sep 16, 2026

Copy link
Copy Markdown
Contributor

View your CI Pipeline Execution ↗ for commit a157506

Command Status Duration Result
nx affected --targets=lint,oxlint,test,build,e2... ✅ Succeeded 6m 48s View ↗
nx run-many -t check-imports check-lock-files c... ✅ Succeeded 4s View ↗
nx-cloud record -- pnpm nx-cloud conformance:check ✅ Succeeded 1m 3s View ↗
nx build workspace-plugin ✅ Succeeded <1s View ↗
nx-cloud record -- nx sync:check ✅ Succeeded 20s View ↗
nx-cloud record -- nx format:check ✅ Succeeded <1s View ↗

☁️ Nx Cloud last updated this comment at 2026-09-16 09:48:26 UTC

@nx-cloud nx-cloud Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nx Cloud has identified a flaky task in your failed CI:

🔂 Since the failure was identified as flaky, we triggered a CI rerun by adding an empty commit to this branch.

Nx Cloud View detailed reasoning in Nx Cloud ↗

🔔 Heads up, your workspace has pending recommendations ↗ to auto-apply fixes for similar failures.


🎓 Learn more about Self-Healing CI on nx.dev

…ed builds

Production builds miscompiled class field initializers that pass a
callback to a helper, such as `injectVirtualizer(() => ...)` from
@tanstack/angular-virtual. The SWC minifier inlined the helper and
hoisted the callback into a variable shared by the enclosing scope, so
every instance read the callback of the last one constructed.

Set `inline: 0` and `reduce_funcs: false` in the SWC compress options for
browser and server builds. Either flag alone still miscompiles.
Production builds miscompiled class field initializers that pass a
callback to a helper when the class came from a dependency that ships
native class fields. The SWC minifier hoisted the callback into a
variable shared by the enclosing scope, so every instance read the
callback of the last one constructed. App code was not affected because
the swc-loader rule compiles it to ES5 first.

Set the same `inline: 0` and `reduce_funcs: false` compress options on the
production minimizer.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

@nx/angular-rspack: Production script optimization breaks injectVirtualizer() instance isolation

1 participant