Adding the esbuild executor to an express preset workspace breaks the serve target
See original GitHub issueCurrent Behavior
Using nx 15, starting with the express preset in a new workspace, adding esbuild to the existing express application breaks the serve target as it is unable to find the built module.
Expected Behavior
Running the serve target builds the application in watch mode and runs the application. (In this case I expect the server to start)
Steps to Reproduce
npx create-nx-workspace --preset=express
yarn add -D @nrwl/esbuild
nx g esbuild-project myapp --skipValidation
// This works fine:
nx build myapp
// This fails to find the generated module:
nx serve myapp
An example of the situation after running the above commands can be found here: https://github.com/b-smets/nx-express-esbuild-reproduce
Failure Logs
Error: Cannot find module 'dist/apps/myapp/main.js'
Require stack:
- /Users/bsmets/git/smos/myrepo/node_modules/@nrwl/js/src/executors/node/node-with-require-overrides.js
at Function.Module._resolveFilename (internal/modules/cjs/loader.js:902:15)
at Function.Module._load (internal/modules/cjs/loader.js:746:27)
at Function.Module._load (/Users/bsmets/git/smos/myrepo/packages/js/src/executors/node/node-with-require-overrides.ts:16:27)
at Module.require (internal/modules/cjs/loader.js:974:19)
at require (internal/modules/cjs/helpers.js:101:18)
at Object.<anonymous> (/Users/bsmets/git/smos/myrepo/packages/js/src/executors/node/node-with-require-overrides.ts:20:1)
at Module._compile (internal/modules/cjs/loader.js:1085:14)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1114:10)
at Module.load (internal/modules/cjs/loader.js:950:32)
at Function.Module._load (internal/modules/cjs/loader.js:790:12)
[ watch ] build succeeded, watching for changes...
I already did some digging and noticed that the require in @nrwl/js/src/executors/node/node-with-require-overrides.js is getting a relative path 'dist/apps/myapp/main.js` whereas using the original webpack build results in an absolute path. I saw that the webpack executor is resolving the output files against the root context (https://github.com/nrwl/nx/blob/master/packages/webpack/src/executors/webpack/webpack.impl.ts#L201) whereas the esbuild executor does not. Is this an oversight or did I miss a configuration anywhere?
Environment
Node : 14.19.3
OS : darwin x64
yarn : 1.22.19
nx : 15.0.0
@nrwl/angular : Not Found
@nrwl/cypress : Not Found
@nrwl/detox : Not Found
@nrwl/devkit : 15.0.0
@nrwl/esbuild : 15.0.0
@nrwl/eslint-plugin-nx : 15.0.0
@nrwl/expo : Not Found
@nrwl/express : 15.0.0
@nrwl/jest : 15.0.0
@nrwl/js : 15.0.0
@nrwl/linter : 15.0.0
@nrwl/nest : Not Found
@nrwl/next : Not Found
@nrwl/node : 15.0.0
@nrwl/nx-cloud : Not Found
@nrwl/nx-plugin : Not Found
@nrwl/react : Not Found
@nrwl/react-native : Not Found
@nrwl/rollup : Not Found
@nrwl/schematics : Not Found
@nrwl/storybook : Not Found
@nrwl/web : Not Found
@nrwl/webpack : 15.0.0
@nrwl/workspace : 15.0.0
typescript : 4.8.4
---------------------------------------
Local workspace plugins:
---------------------------------------
Community plugins:```
Issue Analytics
- State:
- Created a year ago
- Reactions:3
- Comments:6

Top Related StackOverflow Question
I did some more investigating and I found out that this is caused by a mix of the esbuild executor output and @nrwl/js:node executor. Switching to the @nrwl/node:node executor does not help as it just forwards to the previous one.
The problem is as I described in the first post in this thread: esbuild emits an outputfile path relative to the root of the repo whereas webpack results in a resolved absolute path. When invoking the @nrwl/js:node executor,
@nrwl/js/src/executors/node/node-with-require-overrides.tswill perform a require of the output file, but since this is a relative path, the required module is resolved to the current directory which is typically something like<root>/node_modules/@nrwl/js/src/executors/node/leading to the “cannot find module” error. The webpack executor outputting an absolute path works fine as a require of an absolute path ignores the current directory.I tried overriding the current directory but unfortunately this does not seem possible through the options of the @nrwl/js:node executor. Snippet of
packages/js/src/executors/node/node.impl.ts:I think there are two possible solutions:
I am willing to create a pull request to do either one of these fixes if you tell me which one you prefer.
There is also still the issue that esbuild by default emits ESM. While this can be overriden to output CJS instead, ESM seems to be the future of the Javascript ecosystem. However, ESM modules cannot be
require’d but instead should be imported. This will also require a change to the @nrwl/js:node executor but I guess that is a separate ticket.We’re also seeing this error within our Nx workspace. A fix would definitely be appreciated!