nx icon indicating copy to clipboard operation
nx copied to clipboard

Type error when building dependent packages using Node16 Module Setting

Open ajwootto opened this issue 1 year ago • 3 comments

Current Behavior

In Typescript 5.1 with moduleResolution set to Node16, I think there's an issue with the approach Nx uses to handle incremental builds when combined with ESM modules.

Currently if a package A (which is ESM) in your repo depends on another module B, then Typescript will produce type errors when building A complaining that package B can't be resolved. The explanation for this appears to be that Node treats "relative" imports differently from imports of "node_modules", and in ESM it's not possible to "relatively" import a package.

That means that Typescript also errors when moduleResolution is Node16 because it tries to match Node's behaviour. Under the hood, Nx is "swapping" the tsconfig alias for package B when it builds package A, to point to the dist/ directory output of package B. That means it's being treated as a "relative" import by the type system, so it prevents the build from succeeding.

The behaviour of Typescript is explained more here: https://github.com/microsoft/TypeScript/issues/54620#issuecomment-1648618109

Expected Behavior

The strategy Nx uses for incremental building should support Node and Typescript's module resolution behaviour.

Typescript >5 moduleResolution: node16

GitHub Repo

https://github.com/DevCycleHQ/js-sdks/tree/typescript-repro

Steps to Reproduce

  1. Check out the linked branch of our Nx Monorepo
  2. run nx build js
  3. Observe the type errors that occur

the js lib depends on the shared-types lib which is being output to dist/lib/shared/types so you can inspect the output of the package.json there

Nx Report

Node   : 18.16.0
   OS     : darwin arm64
   yarn   : 3.6.0
   Hasher : Native

   nx                 : 16.3.2
   lerna              : 5.6.2
   @nx/js             : 16.3.2
   @nx/jest           : 16.3.2
   @nx/linter         : 16.3.2
   @nx/workspace      : 16.3.2
   @nx/cypress        : 16.3.2
   @nx/detox          : 16.3.2
   @nx/devkit         : 16.3.2
   @nx/esbuild        : 16.3.2
   @nx/eslint-plugin  : 16.3.2
   @nx/next           : 16.3.2
   @nx/node           : 16.3.2
   @nx/react          : 16.3.2
   @nx/react-native   : 16.3.2
   @nx/rollup         : 16.3.2
   @nrwl/tao          : 16.3.2
   @nx/web            : 16.3.2
   @nx/webpack        : 16.3.2
   typescript         : 5.0.4
   ---------------------------------------
   Local workspace plugins:
   	 @devcycle/bucketing-assembly-script
   	 @devcycle/nodejs-server-sdk-cloud-typescript-example
   	 @devcycle/nodejs-server-sdk-local-typescript-example
   	 @devcycle/openfeature-nodejs-provider
   	 @devcycle/bucketing-test-data
   	 @devcycle/js-client-sdk-web-example
   	 with-provider
   	 @devcycle/openfeature-nodejs-example
   	 next-js-app
   	 @devcycle/nodejs-server-sdk-cloud-js-example
   	 @devcycle/nodejs-server-sdk-local-js-example
   	 @devcycle/bucketing
   	 @devcycle/react-native-client-sdk
   	 @devcycle/types
   	 @devcycle/nodejs-server-sdk
   	 @devcycle/react-client-sdk

Failure Logs

No response

Operating System

  • [X] macOS
  • [ ] Linux
  • [ ] Windows
  • [ ] Other (Please specify)

Additional Information

No response

ajwootto avatar Jul 26 '23 15:07 ajwootto

This issue has been automatically marked as stale because it hasn't had any recent activity. It will be closed in 14 days if no further activity occurs. If we missed this issue please reply to keep it active. Thanks for being a part of the Nx community! 🙏

github-actions[bot] avatar Jan 25 '24 00:01 github-actions[bot]

not stale

ajwootto avatar Jan 25 '24 14:01 ajwootto

Just to add more context here, Typescript's docs are now updated with a really good guide on ES modules compatibility. There's a relevant section here about not using paths to link monorepo packages with the main justification being the issue that's reported here https://www.typescriptlang.org/docs/handbook/modules/reference.html#paths-should-not-point-to-monorepo-packages-or-node_modules-packages

Basically I think the fundamental way that Nx links packages is flawed and can't be used in an ES module future where relative package imports are no longer supported. To work properly it would likely need to switch to some kind of system that takes advantage of native workspace linking (supported by all major package managers)

ajwootto avatar Apr 29 '24 15:04 ajwootto