Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to execute node when importing ES Modules - using @nx/js:node executor #21928

Open
1 of 4 tasks
richmondp opened this issue Feb 22, 2024 · 11 comments
Open
1 of 4 tasks
Assignees
Labels
scope: node Issues related to Node, Express, NestJS support for Nx type: bug

Comments

@richmondp
Copy link

Current Behavior

When attempting to execute a node/express application using @nx/js:node executor, if the application imports an ES Module library with the @nrwl/node:node executor the following error is displayed.

.../node_modules/@nx/js/src/executors/node/node-with-require-overrides.js:18
        return originalLoader.apply(this, arguments);
                              ^
Error [ERR_REQUIRE_ESM]: require() of ES Module .../node_modules/lodash-es/lodash.js not supported.
Instead change the require of lodash.js in null to a dynamic import() which is available in all CommonJS modules.

If, I then make some changes to the application in an attempt to support importing ESM modules, I am then faced with another issue in that I cannot import any workspace libraries.

ERROR in ./apps/webpack-mod/src/main.ts 12:0-46 Module not found: Error: Can't resolve '@esm-test/cjs-lib' in '.../esm-test/apps/webpack-mod/src'

Expected Behavior

Should be able to execute a project that imports an ES Module library and workspace libraries which themselves, may or may not import other 3rd party ES Module libraries.

And/or potentially, in the interim, some documentation describing how this can best be achieved in current versions. From reading other threads, this seems to be a common issue raised and with ESM libraries being the recommendation moving forward more and more libraries will move this way. I am assuming there is a way to deal with this, but as yet, I have been unable to find a correct approach (see below for details of each approach). If it is not something that can be easily added to the library then I am open to writing my own executors/generators but I am a little lost as to how to proceed.

I know the examples in the attached repo are very basic and in some cases I could just downgrade a version of a library I need but I have some libraries that this is not possible.

As it stands right now, I am unable to continue using nx because of the issues in executing apps with ESM library dependencies but I don't want to do that because I like the NX ecosystem.

GitHub Repo

https://github.com/b-simpson12/esm-test

Steps to Reproduce

I have attached an git repo of an nx workspace containing a number of different node/express applications. In each app I am trying to import a 3rd party ESM library (in this example lodash-es) as well a 3 workspace JS libraries.

  1. The first library is just a very basic library with no additional imports (out-of-the-box JS library)
  2. The second is a JS library that also imports an ESM library (in this example lodash-es) but no other modifications have been made
  3. And the third library is similar to library Bazel: update to latest rules #2 but it has been modified to set format: ["esm"] in the build config as well as modifications to package.json and tsconfig.lib.json to set it up to be an esm library.

Note: All app have a README outlining how it was created and what changes were made after the out-of-the-box generated code

Applications

dynamic-import: Express application using Dynamic Imports for esm libraries

  1. nx run dynamic-import:build - (Works)
  2. nx run dynamic-import:serve - (Fails with Error [ERR_REQUIRE_ESM]: require() of ES Module)

esbuild-mod: Express application which has been modified to use @nx/esbuild:esbuild as its build executor

  1. nx run esbuild-mod:build - (Fails - does not recognize libs) - WORKS with only esm module import
  2. nx run esbuild-mod:serve - (Fails - does not recognize libs) - WORKS with only esm module import

issue-10565: Node application - based of the directions in Issue 10565

I wanted to see what the outcome of PR 10414 was which seem to indicate that it would fix this issue.

nx run issue-10565:build - (Fails - does not recognize libs) - WORKS with only esm module imports
nx run issue-10565:serve - (Fails - does not recognize libs) - WORKS with only esm module imports

issue-10565: Node application - based of the directions in Issue 10565

Basically the same as issue-105655 but just using the express generator

  1. nx run express-10565:build - (Fails - does not recognize libs) - WORKS with only esm module imports
  2. nx run express-10565:serve - (Fails - does not recognize libs) - WORKS with only esm module imports

node-app: Out-of-the-box Node application

Used to compare the differences between the standard generated Node app and the modifications made in issue-10565

  1. nx run node-app:build - Works
  2. nx run node-app:serve - Fails - Error [ERR_REQUIRE_ESM]: require()

preset-express: Express application created with the workspace using --preset=express

  1. nx run preset-express:build - Works
  2. nx run preset-express:serve - Fails - Error [ERR_REQUIRE_ESM]: require() on esm library import or workspace libraries that have esm imports

webpack-mod: Express applications with modifications to the webpack executor (among other things)

This was based off information in a number of different threads and was pieced together to form this app

  1. nx run webpack-mod:build - (Fails - does not recognize libs) - WORKS with only esm module import
  2. nx run webpack-mod:serve - (Fails - does not recognize libs) - WORKS with only esm module import

control: An express app with no additional imports

Used as a baseline

  1. nx run control:build - Works
  2. nx run control:serve - Works

Nx Report

Node   : 18.18.0
   OS     : darwin-arm64
   npm    : 9.8.1
   
   nx (global)        : 18.0.2
   nx                 : 18.0.4
   @nx/js             : 18.0.4
   @nx/jest           : 18.0.4
   @nx/linter         : 18.0.4
   @nx/eslint         : 18.0.4
   @nx/workspace      : 18.0.4
   @nx/devkit         : 18.0.4
   @nx/esbuild        : 18.0.4
   @nx/eslint-plugin  : 18.0.4
   @nx/express        : 18.0.4
   @nx/nest           : 18.0.4
   @nx/node           : 18.0.4
   @nrwl/tao          : 18.0.4
   @nx/vite           : 18.0.4
   @nx/web            : 18.0.4
   @nx/webpack        : 18.0.4
   typescript         : 5.3.3

Failure Logs

.../node_modules/@nx/js/src/executors/node/node-with-require-overrides.js:18
        return originalLoader.apply(this, arguments);
                              ^
Error [ERR_REQUIRE_ESM]: require() of ES Module .../node_modules/lodash-es/lodash.js not supported.
Instead change the require of lodash.js in null to a dynamic import() which is available in all CommonJS modules.

Package Manager Version

No response

Operating System

  • macOS
  • Linux
  • Windows
  • Other (Please specify)

Additional Information

No response

@AgentEnder AgentEnder added the scope: node Issues related to Node, Express, NestJS support for Nx label Feb 22, 2024
@alx-andru
Copy link
Contributor

@richmondp have you found a solution to this? Running into the same issue

@enchorb
Copy link

enchorb commented May 16, 2024

+1, occurring in v19 also

@danielsharvey
Copy link
Contributor

See also #11335 and my comment #11335 (comment)

@danielsharvey
Copy link
Contributor

In case it is useful, I've published a Node executor including ESM module resolution for buildable libraries within Nx workspaces.

https://www.npmjs.com/package/@harves/nx-node-esm-plugin

@scriptify
Copy link

+1. When will @nx/js:node be ESM compatible?

@lourd
Copy link
Contributor

lourd commented Jun 21, 2024

Also just ran headlong into this. Using nx v19.0.3, developing a Node.js application using @nx/esbuild and @nx/node. Added a library that's published as esm and ran into the same error described by OP.

I switched the format option in the build target from cjs, the default, to esm, which solved the original problem, but then created another problem in that all my imports don't have .js file suffixes and therefore couldn't be found:

Error: Cannot find module '/home/ubuntu/.../app' imported from /home/ubuntu/.../dist/.../main.js
    at finalizeResolution (node:internal/modules/esm/resolve:265:11)
    at moduleResolve (node:internal/modules/esm/resolve:933:10)
    at defaultResolve (node:internal/modules/esm/resolve:1157:11)
    at ModuleLoader.defaultResolve (node:internal/modules/esm/loader:383:12)
    at ModuleLoader.resolve (node:internal/modules/esm/loader:352:25)
    at ModuleLoader.getModuleJob (node:internal/modules/esm/loader:227:38)
    at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:87:39)
    at link (node:internal/modules/esm/module_job:86:36)

I searched around for and found some issues on the esbuild repo like this one about what to do evanw/esbuild#1343 — the TS team says you should manually add .js extensions to your imports instead of having your bundler do it.

I went ahead and did that for my relative imports. But then still ran into an error where I'm importing libraries from elsewhere in my monorepo and those can't be found.

What I ended up going with was specifying "bundle": true for the production and development configurations of my build target, which allowed me to side-step the library import error and having to add .js extensions to my imports. If it's all in one file there's no need to import anything! 🙈

Would definitely appreciate an easier, clearer path here.

@Niewdanka
Copy link

Niewdanka commented Sep 20, 2024

Is there any workaround? This problem has been around for about 2 years now.

@gionkunz
Copy link

gionkunz commented Oct 1, 2024

For me it works by just changing the target and module in tsconfig.json to ES2022 and changing the @nx/esbuild:esbuild executor options to "format": ["esm"],

@itizarsa
Copy link

For me it works by just changing the target and module in tsconfig.json to ES2022 and changing the @nx/esbuild:esbuild executor options to "format": ["esm"],

@gionkunz Could you share a working repo? I have the same options, but it's not working

@gp187
Copy link

gp187 commented Dec 1, 2024

+1

@gotenxds
Copy link

gotenxds commented Dec 26, 2024

Not a solution per se but node 22 lts now supports importing esm modules via require, if you can update your node version to 22.12 and above this is solved for you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
scope: node Issues related to Node, Express, NestJS support for Nx type: bug
Projects
None yet
Development

No branches or pull requests