fix(core): register nodenext esm resolvers at daemon startup - #36708
fix(core): register nodenext esm resolvers at daemon startup#36708llwt wants to merge 2 commits into
Conversation
The daemon is spawned with the workspace's resolve conditions since #36296, so a sync generator's transitive workspace imports resolve to TypeScript source in the daemon process. The NodeNext .js -> .ts resolver hooks were only registered in plugin workers, so those imports failed with ERR_MODULE_NOT_FOUND. Register them at daemon startup, mirroring registerPluginTSTranspiler's native-strip path.
…e typescript source
✅ Deploy Preview for nx-docs ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
✅ Deploy Preview for nx-dev ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
|
View your CI Pipeline Execution ↗ for commit 59c67f0
☁️ Nx Cloud last updated this comment at |
There was a problem hiding this comment.
Nx Cloud has identified a possible root cause for your failed CI:
We investigated all four failing tasks and determined they are unrelated to this PR's changes. Three failures (e2e-remix, e2e-nx-init, e2e-angular) share an identical yarn registry error — @rolldown/binding-*@1.2.5 is unavailable in the CI environment — while the fourth (e2e-react) is a build task timeout where the underlying rollup process actually completed successfully. None of the affected projects are touched by this PR, and re-running should resolve these environment-state failures.
No code changes were suggested for this issue.
Trigger a rerun:
🔔 Heads up, your workspace has pending recommendations ↗ to auto-apply fixes for similar failures.
🎓 Learn more about Self-Healing CI on nx.dev
|
Likely covered by #36725 instead. |
Current Behavior
In a workspace with
customConditionsintsconfig.base.json(e.g. asourcecondition mapping workspace packages to their TypeScript source),nx syncfails when the daemon runs a sync generator that imports a workspace library:Since #36296 (shipped in 23.1.1) the daemon is spawned with the workspace's resolve conditions (
getPluginResolveConditionNodeArgs()), so the generator's transitive workspace imports resolve to TypeScript source. That source uses NodeNext-style.jsspecifiers for.tsfiles, which need Nx's NodeNext resolver hooks, but those hooks were only ever registered in plugin worker processes (viaregisterPluginTSTranspiler()), never in the daemon server process, which loads and runs sync generators in-process. Note the generator entry itself resolves to builtdist/*.js; the TypeScript source enters through the transitive workspace import, so registration has to be process-level rather than tied to loading a.tsentrypoint.NX_DAEMON=falsemasks the bug because the CLI process runs without the injected conditions and resolves the workspace library to its builtdistoutput instead.Expected Behavior
The daemon registers the NodeNext
.js->.tsresolvers (ensureCjsResolverPatched()+ensureNodeNextEsmResolverRegistered()) at startup, gated onisNativeStripPreferred(), mirroringregisterPluginTSTranspiler(). Sync generators whose workspace imports resolve to TypeScript source now load and run in the daemon.Verified red/green against the minimal reproduction https://github.com/mugli/nx-esm-resolve-bug (fails on 23.1.1 and current master without this change, passes with it; the repro's
NODE_OPTIONS --importresolve-hook control also passes). The new e2e (e2e/nx/src/sync.test.ts) mirrors that reproduction, was observed failing with the exact reported error before the fix, and asserts via the daemon log that the generator ran in the daemon process rather than a silently daemon-less fallback.Related Issue(s)
No open GitHub issue. Reported in the Nx Slack (thread https://nrwl.slack.com/archives/C095YGAEJ1L/p1787141198800679?thread_ts=1769434770.555049&cid=C095YGAEJ1L) with the minimal reproduction https://github.com/mugli/nx-esm-resolve-bug.
View Polygraph session ↗