Loading workspace insights... Statistics interval
7 days30 daysLatest CI Pipeline Executions
5fbdca96 fix(core): prefer module.registerHooks to avoid DEP0205 deprecation warning (#36081)
## Current Behavior
To support TypeScript NodeNext-style relative imports under Node's
native type
stripping, Nx registers a small ESM resolution hook that rewrites
`.js`/`.mjs`/`.cjs` specifiers to their `.ts`/`.mts`/`.cts` sources. It
did this
with `module.register()`.
`module.register()` is runtime-deprecated on Node 25.9+ / 26+ (DEP0205),
so
loading a `.ts` config emitted a warning. For example, building a
project with a
TypeScript webpack config:
```
> webpack-cli build
(node:839660) [DEP0205] DeprecationWarning: `module.register()` is deprecated. Use `module.registerHooks()` instead.
(Use `node --trace-deprecation ...` to show where the warning was created)
```
The build still succeeded; the warning was just noise.
## Expected Behavior
Nx now prefers `module.registerHooks()` (added in Node 22.15.0 /
23.5.0), which
runs the resolve hook synchronously in-thread and is not deprecated. No
more
`DEP0205` warning on Node 22.15+ / 24 / 26.
It falls back to `module.register()` only on older supported runtimes
that lack
`registerHooks` ā Node `22.12.0`ā`22.14.x` (within the current
`^22.12.0`
support floor, and CI-tested at `22.13.0`). On those versions
`module.register()`
is not yet deprecated, so the fallback stays silent.
Implementation notes:
- Added `nodeNextEsmResolveHook`, a synchronous in-thread twin of the
existing
inlined `data:`-module resolver (`NODENEXT_ESM_RESOLVER_SOURCE`). With
`registerHooks`, `nextResolve` throws synchronously rather than
rejecting a
promise, so the hook uses plain try/catch instead of `await`.
- The existing `isTsTranspilerPreloaded()` skip is kept for both paths
so
resolver coverage doesn't vary by Node version.
- The inlined `data:` source is retained for the fallback and marked as
such.
- Added unit tests mirroring all existing resolver cases against the new
synchronous hook.
The third-party ESM loader registration in `forceRegisterEsmLoader`
(`@swc-node/register/esm` / `ts-node/esm`) intentionally still uses
`module.register()`: those are asynchronous worker-thread loaders with
no
synchronous `registerHooks` equivalent, and that path only fires in a
niche
escalation (top-level await + TS syntax native strip can't handle).
## Related Issue(s)
N/A
---------
Co-authored-by: nx-cloud[bot] <71083854+nx-cloud[bot]@users.noreply.github.com>