Nx
Enterprise
Nx
fix(core): support local plugins using NodeNext .js import specifiers (#35834) ## Current Behavior Loading a local Nx plugin from its TypeScript source (via the `development`/source export condition, including secondary entry points) fails when the source uses NodeNext-style explicit `.js` relative imports — `import './nodes.js'` where the file on disk is `nodes.ts`. Any `nx` command that builds the project graph errors with `Cannot find module './nodes.js'`. Node's native TypeScript stripping loads the `.ts` source but does not rewrite the explicit `.js` specifier to its `.ts` sibling, and nothing in the plugin-loading path did either. ## Expected Behavior Local plugins whose TypeScript sources use NodeNext `.js` import specifiers load correctly from source, for both `type: module` (ESM) and `type: commonjs` packages. ## Implementation Details Add dependency-free `.js` → `.ts` resolution on the native-strip plugin-loading path, mirroring how `tsx` / `ts-node`'s `experimentalResolver` patch module resolution: - **CJS:** a `Module._resolveFilename` fallback that rewrites `.js`/`.mjs`/`.cjs` → `.ts`/`.tsx`/`.mts`/`.cts` when the requesting module is itself TypeScript and the `.js` file doesn't exist. - **ESM:** a self-contained inline `module.register` resolve hook (no `ts-node`/`swc-node` dependency) that does the same on the dynamic-import path, leaving Node's native stripping to load the resolved `.ts` — preserving true ESM semantics. Both are best-effort, fire only on a not-found error, and never alter resolutions that already succeed. `type: commonjs` sources still rely on the existing swc/ts-node fallback to transpile their `import` syntax (native strip can't run ESM syntax in a CJS module), after which the CJS resolver patch handles the emitted `require('./x.js')`. > [!NOTE] > The ESM resolve hook is skipped when a transpiler is preloaded via `--require`/`--import` (e.g. `--require ts-node/register`), which only happens when Nx itself runs from `.ts` source — registering it there would crash the `module.register` loader-hook worker. Published Nx (compiled `.js` workers, no preload) is unaffected.
nx-cloud record -- nx sync:check
Sign in / Sign up
Open main menu
Succeeded
CI Pipeline Execution
1 run failed
nx-cloud record -- nx sync:check
Click to copy
Linux
4 CPU cores
7438746d
master