Skip to content

feat(ts#react-website): override the express @nx/react resolves to, and take nx 23.1.2 - #1148

Merged
cogwirrel merged 1 commit into
mainfrom
feat/nx-23.1.2-react-express-override
Aug 28, 2026
Merged

feat(ts#react-website): override the express @nx/react resolves to, and take nx 23.1.2#1148
cogwirrel merged 1 commit into
mainfrom
feat/nx-23.1.2-react-express-override

Conversation

@nx-plugin-for-aws

Copy link
Copy Markdown
Collaborator

Reason for this change

The nx 23.1.2 bump was held back in #1145 because it broke Smoke Tests - npm. @nx/react 23.1.2 adds an optional express peer that 23.1.1 did not declare:

$ npm view @nx/react@23.1.1 peerDependencies   # react, react-dom, babel-plugin-react-compiler
$ npm view @nx/react@23.1.2 peerDependencies   # ...plus express ^4.21.2, @nx/module-federation, http-proxy-middleware

It is for the module-federation dev-server, and it is optional (peerDependenciesMeta.express.optional: true) — nothing in a generated workspace loads express through @nx/react. But generated projects pin express 5.2.1, the major @strands-agents/sdk peers on (express: ^5.1.0), and npm fails the whole install on an optional peer it cannot satisfy:

npm error ERESOLVE could not resolve
npm error Found: express@4.22.2
npm error   peerOptional express@"^4.21.2" from @nx/react@23.1.2
npm error Conflicting peer dependency: express@5.2.1
npm error   peerOptional express@"^5.1.0" from @strands-agents/sdk@1.14.0

I checked all five package managers against the conflict directly: only npm fails. pnpm, bun, yarn 4 and yarn classic install and emit a warning. Since 23.1.2 is the latest nx release, holding back was the only option at the time — this unblocks it.

Description of changes

Vend a scoped npm override. ts#react-website pins the express @nx/react resolves to, via npm's overrides:

"overrides": { "@nx/react": { "express": "5.2.1" } }

Scoped to @nx/react rather than pinning express workspace-wide: the peer only has to be satisfiable, so this keeps npm's check honest for every other consumer of express and installs no second copy (verified in the lockfile — one node_modules/express, at 5.2.1).

This follows the existing precedent in terraform#project, which resolves the same class of upstream peer conflict the same way (@nx-extend/terraform's @nx/devkit peer), including declaring the dependency versionOnly purely to feed the override.

express is declared versionOnly, so the version sync owns it. The pin is reachable only through the override, so without this a stale override would silently rot and break npm resolution once the vended express moves on. There's a test asserting the sync carries it forward.

Take nx 23.1.2 across versions.ts, both package.jsons, and register the nx-23.1.2-nx-packages packageJsonUpdates entry.

A migration adds the override to existing workspaces, which would otherwise be unable to install once their nx moves onto 23.1.2. It is npm-only, skips a workspace with no website, keeps a version the user pinned deliberately, and reports (rather than clobbers) the string-form overrides['@nx/react'] case it cannot safely nest under.

Description of how you validated changes

  • Reproduced the failure and the fix against real npm resolution, in a workspace shaped like the generated one (root @nx/react 23.1.2 + express 5.2.1 + @strands-agents/sdk): ERESOLVE without the override, up to date with it, and a lockfile carrying exactly one express at 5.2.1. This is the check that matters — the failure was npm's resolver, not anything a unit test sees.
  • Confirmed the scope of the problem by installing that same manifest under npm, pnpm, bun, yarn 4 and yarn classic, which is what established the override should be npm-only.
  • pnpm nx test nx-plugin3940 tests pass across 218 files. New tests: the override is written on npm; it is not written on pnpm/yarn/bun; the version sync carries it forward; plus 9 migration tests (applies, preserves sibling keys and other overrides, skips non-npm, skips a workspace with no website, keeps a user's pin, reports the string form, idempotent).
  • Snapshots show the override in generated output and nx at 23.1.2.
  • pnpm lint and pnpm nx sync pass; LICENSE-THIRD-PARTY regenerated.

Note the smoke tests are the real gate here, since they run actual installs across every package manager — worth watching on this PR specifically.

Issue # (if applicable)

N/A — follows on from #1145, which held the bump back.

Checklist


By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license

…nd take nx 23.1.2

@nx/react 23.1.2 adds an optional `express: ^4.21.2` peer for its
module-federation dev-server, a major behind the express generated
projects use (`@strands-agents/sdk` peers on `^5.1.0`). npm alone fails
the whole install on an optional peer it cannot satisfy:

  npm error ERESOLVE could not resolve
  npm error   peerOptional express@"^4.21.2" from @nx/react@23.1.2
  npm error Conflicting peer dependency: express@5.2.1

pnpm, bun, yarn 4 and yarn classic all install and only warn, which is
why holding nx back was the way to land the last dependency update.

Nothing in a generated workspace loads express through @nx/react — the
peer only has to be satisfiable — so pin it to the version already vended
via npm's `overrides`, scoped to `@nx/react` so every other consumer of
express keeps its own resolution and no second copy is installed. This
follows terraform#project, which resolves the same class of upstream peer
conflict the same way.

`express` is declared `versionOnly`, so the version sync owns it: the pin
is reachable only through the override, and a stale one would leave npm
unable to resolve once the vended express moves on.

A migration adds the override to workspaces that already have a website,
which would otherwise be unable to install once their nx moves onto
23.1.2. It is npm-only, skips a workspace with no website, keeps a version
the user pinned deliberately, and reports the string-form
`overrides['@nx/react']` case it cannot safely nest under.
@codecov-commenter

codecov-commenter commented Aug 28, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 88.59%. Comparing base (7201b80) to head (e3af59a).

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1148      +/-   ##
==========================================
+ Coverage   88.51%   88.59%   +0.08%     
==========================================
  Files         245      246       +1     
  Lines       10464    10485      +21     
  Branches     2476     2482       +6     
==========================================
+ Hits         9262     9289      +27     
+ Misses        524      521       -3     
+ Partials      678      675       -3     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@cogwirrel
cogwirrel merged commit b810f24 into main Aug 28, 2026
62 checks passed
@cogwirrel
cogwirrel deleted the feat/nx-23.1.2-react-express-override branch August 28, 2026 14:19
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.

3 participants