feat(rspack): support @rspack/core@2 and @rsbuild/core@2 (multi-version compliance)#35682
Conversation
✅ Deploy Preview for nx-dev ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
✅ Deploy Preview for nx-docs ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
|
View your CI Pipeline Execution ↗ for commit 8c04f14
☁️ Nx Cloud last updated this comment at |
329a4d1 to
8ea2d24
Compare
|
All alerts resolved. Learn more about Socket for GitHub. This PR previously contained dependency changes with security issues that have been resolved, removed, or ignored. |
8cad94e to
ca11bc6
Compare
65949fc to
11d4251
Compare
There was a problem hiding this comment.
Important
At least one additional CI pipeline execution has run since the conclusion below was written and it may no longer be applicable.
Nx Cloud is proposing a fix for your failed CI:
We add a null guard at the top of the compiler.hooks.afterDone tap callback in AngularRspackPlugin so that rspackStatsLogger is never invoked with an undefined stats argument. In @rspack/core v2 the afterDone hook can fire without a stats object when a compilation terminates in an error path before stats are generated, which was the direct cause of the TypeError: Cannot read properties of undefined (reading 'toJson') crash seen across all 13 examples-angular-rspack-*:build tasks. Both the TypeScript source and the compiled dist file are patched so the fix takes effect immediately regardless of cache state.
Note
⏳ We are verifying this fix by re-running a subset of the 19 failed tasks that were analyzed.
diff --git a/packages/angular-rspack/src/lib/plugins/angular-rspack-plugin.ts b/packages/angular-rspack/src/lib/plugins/angular-rspack-plugin.ts
index a98ea014..c984c436 100644
--- a/packages/angular-rspack/src/lib/plugins/angular-rspack-plugin.ts
+++ b/packages/angular-rspack/src/lib/plugins/angular-rspack-plugin.ts
@@ -325,6 +325,11 @@ export class AngularRspackPlugin implements RspackPluginInstance {
});
compiler.hooks.afterDone.tap(PLUGIN_NAME, (stats) => {
+ // In @rspack/core v2, afterDone may fire with undefined stats when a
+ // compilation terminates in an error path before stats are generated.
+ if (!stats) {
+ return;
+ }
// Get stats options - merge defaults with user's config if provided
const configStats = compiler.options.stats;
const defaultStatsOptions = getStatsOptions(this.#_options.verbose);
Or Apply changes locally with:
npx nx-cloud apply-locally XFa0-Pf0N
Apply fix locally with your editor ↗ View interactive diff ↗
🎓 Learn more about Self-Healing CI on nx.dev
cbfb651 to
18b2714
Compare
10533f2 to
2da1a30
Compare
dd8d4a5 to
6f17e62
Compare
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
26aeff8 to
c16b92c
Compare
Cypress 15.x bundled tsx 4.20.6 which did not synthesize import.meta.dirname, breaking @rspack/core@2 (which uses it in its CJS bundle) when run under Cypress's tsx require-hook. 15.17.0 ships tsx 4.22.4, which restores the synthesis. Adds a 23.0.0-beta.26 packageJsonUpdates entry so workspaces on cypress <15.17.0 pick up the fix on migrate. Exempts cypress from the minimumReleaseAge guard so the bump can land before the 24h supply-chain cooldown elapses.
Aligns the v1->v2 packageJsonUpdates and module-federation gated entries to the current 23.0.0 beta cut so they ship in the same release window. Also bumps the rsbuild migrations to keep the v2 transition aligned.
Replace the six inline process.env['WEBPACK_SERVE'] reads with isServeMode() from a new rspack-serve-env util. The util also exports bridgeRspackServeEnv(), which createConfig calls to keep cross-package consumers (generated rspack configs, module-federation plugins) working on rspack 2. isServeMode falls back to argv when the env var is unset, so AngularRspackPlugin instantiated outside createConfig also reports serve mode correctly.
@rspack/dev-server v2 sets process.env.RSPACK_SERVE at module load, just like v1's webpack-dev-server set WEBPACK_SERVE. rspack-cli imports @rspack/dev-server before invoking the config loader for the serve and preview commands, so the env var is reliably present by the time createConfig runs. Check it directly instead of sniffing process.argv, and drop the bridge helper — every angular-rspack call site now uses isServeMode().
Replace the eleven inline process.env['WEBPACK_SERVE'] reads across the angular/rspack/webpack dev-server plugins and with-module-federation helpers with a shared isServeMode() util that checks both WEBPACK_SERVE (v1) and RSPACK_SERVE (v2). @rspack/dev-server v2 sets RSPACK_SERVE on module load, and rspack-cli imports it before loading the user config, so the env var is available without any argv sniff or bridge step. Delete bridge-rspack-serve-env now that no caller needs the WEBPACK_SERVE variable specifically.
… builds Trim the multi-line v1/v2 explainers, redundant docstrings, and codepath- restatement comments added during the rspack 2 work down to the essential WHY. Drop the WEBPACK_SERVE='false' override in build-static-remotes — the string 'false' is truthy so it never disabled serve detection; delete both WEBPACK_SERVE and RSPACK_SERVE from the spawn env via the new childBuildEnv() helper so the child build doesn't masquerade as a serve.
…ins bridge Replace the two inline process.env['WEBPACK_SERVE'] reads in apply-base-config with isServeMode(), which also accepts RSPACK_SERVE (v2's signal). With those reads gone, the composePlugins bridge that synced ctx.env.RSPACK_SERVE to process.env.WEBPACK_SERVE has no remaining consumer — rspack-cli's serve command already imports @rspack/dev-server (which sets process.env.RSPACK_SERVE) before invoking the config loader. Drop the bridge.
rspack 1.x's ProgressPlugin wrapper spreads its third callback arg (progress(p, msg, ...items)) and crashes when the native binding passes undefined. Fixed upstream only in rspack 2.x. Tap compile/invalid/done compiler hooks directly instead of extending the built-in plugin.
… compiler The static @rspack/core import can be a different major than the rspack actually running the build (e.g. repo dist on v1 driving an app on v2). getCompilationHooks rejects Compilation instances from a foreign copy, so pull the javascript namespace off compiler.rspack instead.
… compiler [Self-Healing CI Rerun]
[email protected] is past the 24h release-age window; the temporary exclusion is no longer needed.
@rspack/plugin-react-refresh@2 is pure ESM and only exports the named ReactRefreshRspackPlugin; require(esm) returns a namespace with no default, so 'mod.default ?? mod' produced a non-constructor and every react dev-serve crashed with 'ReactRefreshPlugin is not a constructor'.
… apps
rspack-cli@2 dev mode auto-enables lazyCompilation { imports: true }
unless the exported config sets it explicitly. The lazy-compilation
proxy wraps the import('./bootstrap') entry of federated apps and its
update chunk 404s under the MF dev-server, so remotes render a blank
page. Set lazyCompilation: false in the generated MF rspack configs,
default it in withModuleFederation, and insert it into existing MF
configs via the v2 config migration.
… apps [Self-Healing CI Rerun]
@rspack/dev-server@2 prints 'Local:' where v1 printed 'Loopback:', so the serve-readiness check timed out even though the server was up.
The old WEBPACK_SERVE: 'false' override was a truthy string, so static remote child builds always ran with a serve signal and angular-rspack picked its development configuration. Removing the override flipped them to production, where default Angular bundle budgets fail freshly generated apps. Signal the intent explicitly via NGRS_CONFIG=development (respecting a user-provided value).
nx checks a migration requires range against the version the package is bumped TO. The config-rewrite migrations were gated >=1.0.0 <2.0.0, so the v2 bump failed the gate and the migrations were skipped. Gate on >=2.0.0 so they run when the user lands on v2, matching the vite/vitest convention. Also retarget the rspack v2 migration entries to 23.1.0-beta.0.
Same fix as rspack: gate the config-rewrite migrations on >=2.0.0 instead of >=1.0.0 <2.0.0 so they run when the user upgrades to rsbuild v2 rather than being skipped. Also retarget the rsbuild v2 migration entries to 23.1.0-beta.0.
Move the cypress 15.17 packageJsonUpdate from 23.0.0-beta.26 to 23.1.0-beta.0 alongside the rspack/rsbuild v2 migrations.
The rspack-version helper used a top-level value import of @rspack/core, re-introducing the eager load the rest of the change avoids and pulling it back transitively through common-config and browser-config. These call sites run at config-build time, before a compiler exists, so defer the read with a lazy require, matching apply-base-config.
The async conversion was leftover from an abandoned await import() approach; the helper bodies do no async work. Returning a Promise gratuitously widened the contract of these deprecated helpers. Revert to sync; the executor already awaits and composePlugins handles sync plugins, so behavior is unchanged.
d0a22de to
8c04f14
Compare
…eywords (#36326) ## Current Behavior `nx release changelog` extracts issue references from the commit body with a bare `/(#\d+)/gm` regex, so **every** `#number` in a squashed PR description becomes an issue link in the changelog — including other repos' issue numbers. For example, the [23.1.0 release notes](https://github.com/nrwl/nx/releases/tag/23.1.0) contain: > **rspack:** support @rspack/core@2 and @rsbuild/core@2 (multi-version compliance) (#35682, #35764, #13420, #781) where `#13420` is actually `web-infra-dev/rspack#13420` and `#781` is `privatenumber/tsx#781` — upstream issues discussed in the PR description, rendered as (bogus) `nrwl/nx` issue links. The same release also picked up `nrwl/nx-console#3175`, `react/react#418`, and `web-infra-dev/rspack#2292`, plus noisy same-repo PR mentions that were merely referenced in prose. ## Expected Behavior Issue references are only extracted from the commit body when linked via a GitHub closing keyword (`Fixes #123`, `Closes #123`, `Resolves: #123`, ...) — the same rule GitHub itself uses to auto-link and close issues. Cross-repo forms (`owner/repo#123`), markdown links to other repos, and casual same-repo mentions no longer produce changelog references. Subject-line extraction (the PR number in `(#123)` and inline issue refs) is unchanged. Both regular commits and version plans go through the same `extractReferencesFromCommit` function, so this fixes both paths. ## Related Issue(s) N/A <!-- polygraph-session-start --> --- [View session information ↗](https://app.trypolygraph.com/orgs/6a061dcb561c062131116eca/sessions/Fix-nx-release-changelog-scraping-other-repos-issue-numbers-7967dd62) <!-- polygraph-session-end -->
…eywords (#36326) ## Current Behavior `nx release changelog` extracts issue references from the commit body with a bare `/(#\d+)/gm` regex, so **every** `#number` in a squashed PR description becomes an issue link in the changelog — including other repos' issue numbers. For example, the [23.1.0 release notes](https://github.com/nrwl/nx/releases/tag/23.1.0) contain: > **rspack:** support @rspack/core@2 and @rsbuild/core@2 (multi-version compliance) (#35682, #35764, #13420, #781) where `#13420` is actually `web-infra-dev/rspack#13420` and `#781` is `privatenumber/tsx#781` — upstream issues discussed in the PR description, rendered as (bogus) `nrwl/nx` issue links. The same release also picked up `nrwl/nx-console#3175`, `react/react#418`, and `web-infra-dev/rspack#2292`, plus noisy same-repo PR mentions that were merely referenced in prose. ## Expected Behavior Issue references are only extracted from the commit body when linked via a GitHub closing keyword (`Fixes #123`, `Closes #123`, `Resolves: #123`, ...) — the same rule GitHub itself uses to auto-link and close issues. Cross-repo forms (`owner/repo#123`), markdown links to other repos, and casual same-repo mentions no longer produce changelog references. Subject-line extraction (the PR number in `(#123)` and inline issue refs) is unchanged. Both regular commits and version plans go through the same `extractReferencesFromCommit` function, so this fixes both paths. ## Related Issue(s) N/A <!-- polygraph-session-start --> --- [View session information ↗](https://app.trypolygraph.com/orgs/6a061dcb561c062131116eca/sessions/Fix-nx-release-changelog-scraping-other-repos-issue-numbers-7967dd62) <!-- polygraph-session-end -->
…eywords (#36326) ## Current Behavior `nx release changelog` extracts issue references from the commit body with a bare `/(#\d+)/gm` regex, so **every** `#number` in a squashed PR description becomes an issue link in the changelog — including other repos' issue numbers. For example, the [23.1.0 release notes](https://github.com/nrwl/nx/releases/tag/23.1.0) contain: > **rspack:** support @rspack/core@2 and @rsbuild/core@2 (multi-version compliance) (#35682, #35764, #13420, #781) where `#13420` is actually `web-infra-dev/rspack#13420` and `#781` is `privatenumber/tsx#781` — upstream issues discussed in the PR description, rendered as (bogus) `nrwl/nx` issue links. The same release also picked up `nrwl/nx-console#3175`, `react/react#418`, and `web-infra-dev/rspack#2292`, plus noisy same-repo PR mentions that were merely referenced in prose. ## Expected Behavior Issue references are only extracted from the commit body when linked via a GitHub closing keyword (`Fixes #123`, `Closes #123`, `Resolves: #123`, ...) — the same rule GitHub itself uses to auto-link and close issues. Cross-repo forms (`owner/repo#123`), markdown links to other repos, and casual same-repo mentions no longer produce changelog references. Subject-line extraction (the PR number in `(#123)` and inline issue refs) is unchanged. Both regular commits and version plans go through the same `extractReferencesFromCommit` function, so this fixes both paths. ## Related Issue(s) N/A <!-- polygraph-session-start --> --- [View session information ↗](https://app.trypolygraph.com/orgs/6a061dcb561c062131116eca/sessions/Fix-nx-release-changelog-scraping-other-repos-issue-numbers-7967dd62) <!-- polygraph-session-end --> (cherry picked from commit d7312d2)
Summary
Adds support for
@rspack/core@2and@rsbuild/core@2across@nx/rspack,@nx/rsbuild,@nx/angular-rspack, and@nx/module-federation. v1 stays in the supported window (multi-version policy: latest + previous major).@rspack/[email protected]/@rsbuild/[email protected].packageJsonUpdatesmigrations move workspaces still on@rspack/core@^1/@rsbuild/core@^1to v2 (23.0.0-beta.20, gated byrequires).v2 breaking changes and how each is handled
1.
@rspack/core@2is pure ESM at the entry, but the bundle is CJSA direct top-level
importfrom@rspack/coreno longer works in places where Nx loads its own plugin modules synchronously. The CJSdist/index.jsis what actually resolves underrequire().Addressed: lazy-load
@rspack/corewhere Nx eagerly imported it, so the import is deferred until the consuming code actually runs. Seefeat(rspack): load @rspack/core lazily for v2 esm compatibility.2.
@rspack/dev-server@2is a ground-up rewrite — no longer wrapswebpack-dev-serverv1's
@rspack/dev-serverdepended onwebpack-dev-server, whoseServer.jssetsprocess.env.WEBPACK_SERVE = 'true'at module load. v2 dropped that dependency entirely; the env var is never set. The rspack 2 CLI signals serve mode viasetBuiltinEnvArg(env, 'SERVE', true)→RSPACK_SERVEon the config-functionenvarg, notprocess.env.Every
process.env['WEBPACK_SERVE']check across@nx/rspack,@nx/angular-rspack, and@nx/module-federationwould silently fall through to build mode on rspack 2.Addressed by three bridges — one per config-shape:
composePlugins-based configs (most@nx/rspackuser configs): bridge incomposePlugins.combinedreadsctx['env']['RSPACK_SERVE']and setsprocess.env.WEBPACK_SERVE. Seefix(rspack): bridge rspack 2 RSPACK_SERVE to WEBPACK_SERVE.createConfig-based configs (@nx/angular-rspackexport default createConfig(...)): rspack never passesenvto value exports, so the env-arg bridge can't run. argv-based detection insidecreateConfig(process.argv[2] ∈ {serve, server, s, dev}) instead. Seefix(angular-rspack): bridge rspack 2 serve signal via argv detection.@nx/react:hostgeneratedrspack.config.tsis an object literal, not a function): neither bridge above runs. SharedbridgeRspackServeEnv()helper called at the top of each MF dev-server plugin'sapply(). Seefix(module-federation): bridge rspack 2 serve signal in dev-server plugins.3. Tightened
RuleSetRuletypings broke flattenedoneOfshapesThe v2 type refactor revealed that
rules: [{ oneOf: [...] }, { use }](master) andoneOf: [..., { use }](the simplification attempt) are not equivalent. FlatoneOfpicks a single matching branch — language loaders left as a siblingusegot dropped for tagged style files.
Addressed: concatenate language loaders into each
oneOfbranch instyle-config-utils.tsso tagged files still preprocess. Seefix(angular-rspack): apply language loaders to tagged style files.4.
experiments.outputModuleno longer accepted in the same shapeSetting
experiments.outputModule: trueis a v1 idiom; on v2 it surfaces as a warning/typing issue depending on the context.Addressed: only set it on v1, omit on v2. See
fix(angular-rspack): omit experiments.outputModule on rspack v2andfix(module-federation): only set experiments.outputModule on rspack v1.5.
stats.profile/statsJsonno longer accept the v1 shapeThe v1 profile/stats notices fired on v2 spuriously.
Addressed: drop the v1-only branch on v2, keep an informational notice for plugin authors. See
fix(angular-rspack): drop the v2 statsJson notice,fix(rspack): drop the v2 statsJson profile warning.6.
afterDonemay fire withundefinedstats on errorv2 propagates compilation errors via the run callback before
afterDoneresolves; the hook is still called butstatsisundefined, masking the real error.Addressed: guard with
if (!stats) return;. Seefix(angular-rspack): guard afterDone handler against undefined stats.7.
--watchflag rename in@rsbuild/core@2The plugin snapshot diverged from the renamed flag.
Addressed: sync snapshot. See
fix(rsbuild): sync plugin snapshot to renamed watch flag.8. Peer-dep auto-install picks first satisfiable sub-range
@nx/angular-rspack's peer was>=1.3.5 <1.7.0 || ^2.0.0. pnpm'sauto-install-peersresolves multi-major OR ranges against the first satisfiable sub-range, so v2 catalogs were ending up with stray@rspack/[email protected].Addressed: reverse to
^2.0.0 || >=1.3.5 <1.7.0. Empirically verified the v1 sub-range no longer steals resolution. Seefix(angular-rspack): order @rspack/core peer range v2-first.9. Migrations + v1→v2
packageJsonUpdatespackages/rspack/migrations.json: new23.0.0-rspack-v2packageJsonUpdates entry (gated byrequires: { "@rspack/core": ">=1.0.0 <2.0.0" }) bumps@rspack/core+ siblings to^2.0.4. Plusrequiresgates added to existingmodule-federation migrations (21.3.0, 22.2.0).
packages/rsbuild/migrations.json: new23.0.0-rsbuild-v2packageJsonUpdates entry (gated similarly) bumps to^2.0.7.23.0.0-beta.20.10. Docs
Supported-versions windows widened to include v2 in both rspack and rsbuild docs pages.
Known limitation:
rspack serveunder Cypress 15The
should have interop between rspack host and webpack remotecase ine2e/react/src/module-federation/misc-rspack-interoperability.test.ts(re-enabled in master via #35764) hits an upstream incompatibility when an rspack 2 dev serveris launched under Cypress 15's e2e runner:
Root cause (three layers):
@rspack/core@2shipsimport.meta.dirnamein its CJS bundle (dist/index.js, lines 2549 + 3462) without a__dirnamefallback.[email protected]inside the Electron app and registers it as a global CJS require-hook. The subprocess spawned fornx run shell:serveinherits this viaNODE_OPTIONS.[email protected]doesn't synthesizeimport.meta.dirnamewhen transforming CJS, so the value isundefinedandpath.join(undefined, …)throws.Upstream status:
Scope: only the
rspack hostbranch of the interop test trips it.webpack host + rspack remotepasses (norspack serveunder Cypress).Decision: leave the test as-is, do not skip — once Cypress ships with bundled tsx ≥ 4.22.0, the failure clears on its own.
Test Plan
nx run-many -t test,build,lint -p rspack,rsbuild,angular-rspack,module-federationnx affected -t build,test,lintnx affected -t e2e-local(see Known limitation above)@rspack/core@^1,^2,@rsbuild/core@^1,^2. Init + build + serve. Confirm no version overwrite.Fixes NXC-4460