nrwl / nx

Smart Monorepos · Fast CI
https://nx.dev
MIT License
23.17k stars 2.3k forks source link

Third party dependencies not bundled when using @nx/esbuild:esbuild executor with bundle flag set #21133

Open thdk opened 7 months ago

thdk commented 7 months ago

Current Behavior

When enabling the bundle option of the @nx/esbuild:esbuild executor, then the third party dependencies are not present in the bundle. Instead, they are automatically marked as external and therefor not included.

This is not expected since the generated Dockerfile says that external dependencies would be included when using the bundle option with esbuild.

npx nx g @nx/node:app --name api --directory apps/api --framework fastify --docker --e2eTestRunner none --projectNameAndRootFormat as-provided

Then a Dockerfile is generated:

# This file is generated by Nx.
#
# Build the docker image with `npx nx docker-build api`.
# Tip: Modify "docker-build" options in project.json to change docker build args.
#
# Run the container with `docker run -p 3000:3000 -t api`.
FROM docker.io/node:lts-alpine

ENV HOST=0.0.0.0
ENV PORT=3000

WORKDIR /app

RUN addgroup --system api && \
          adduser --system -G api api

COPY dist/apps/api api
RUN chown -R api:api .

# You can remove this install step if you build with `--bundle` option.
# The bundled output will include external dependencies.
RUN npm --prefix api --omit=dev -f install

CMD [ "node", "api" ]

Saying that the install step can be removed when using --bundle.

Expected Behavior

All dependencies should be bundled together with the source code so the install step in the Dockerfile can be removed as suggested in the comments of that Dockerfile.

GitHub Repo

https://github.com/thdk/nx-esbuild-bundle-docker-repro

Steps to Reproduce

  1. Create new workspace and add a node application

    npx create-nx-workspace@latest nx-esbuild-app --preset ts
    cd nx-esbuild-app
    npm i -D @nx/node
    npx nx g @nx/node:app --name api --directory apps/api --framework fastify --docker --e2eTestRunner none --projectNameAndRootFormat as-provided
  2. Remove the npm install line from apps/api/Dockerfile

  3. Set bundle option to true in build target of apps/api/project.json

  4. Build container image

npx nx docker-build api
  1. Run the application using image
docker run api

=>

node:internal/modules/cjs/loader:1051
  throw err;
  ^

Error: Cannot find module 'fastify'
Require stack:
- /app/api/main.js
    at Module._resolveFilename (node:internal/modules/cjs/loader:1048:15)
    at Module._load (node:internal/modules/cjs/loader:901:27)
    at Module.require (node:internal/modules/cjs/loader:1115:19)
    at require (node:internal/modules/helpers:130:18)
    at Object.<anonymous> (/app/api/main.js:25:30)
    at Module._compile (node:internal/modules/cjs/loader:1241:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1295:10)
    at Module.load (node:internal/modules/cjs/loader:1091:32)
    at Module._load (node:internal/modules/cjs/loader:938:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:83:12) {
  code: 'MODULE_NOT_FOUND',
  requireStack: [ '/app/api/main.js' ]
}

Node.js v20.9.0

Nx Report

Node   : 20.10.0
   OS     : darwin-arm64
   npm    : 10.2.3

   nx                 : 17.2.8
   @nx/js             : 17.2.8
   @nx/jest           : 17.2.8
   @nx/linter         : 17.2.8
   @nx/eslint         : 17.2.8
   @nx/workspace      : 17.2.8
   @nx/devkit         : 17.2.8
   @nx/esbuild        : 17.2.8
   @nx/eslint-plugin  : 17.2.8
   @nx/node           : 17.2.8
   @nrwl/tao          : 17.2.8
   typescript         : 5.2.2

Failure Logs

No response

Package Manager Version

No response

Operating System

Additional Information

Seems like the issue could be with the following code where esbuild options are being generated.

https://github.com/nrwl/nx/blob/1d2bfde11a76af602ea7f3bc311245ef3c65ec35/packages/esbuild/src/executors/esbuild/lib/build-esbuild-options.ts#L25-L49

external option is being filled by the esbuild executor here: https://github.com/nrwl/nx/blob/1d2bfde11a76af602ea7f3bc311245ef3c65ec35/packages/esbuild/src/executors/esbuild/esbuild.impl.ts#L50-L72

dlfk99 commented 7 months ago

Maybe this will help: https://nx.dev/nx-api/esbuild/executors/esbuild#thirdparty

Try to set the thirdParty option to true and build again. It did the trick for me (after struggling for quite a while). As I understand it the option gives you more control about the bundling scope.

maora-cybi commented 5 months ago

Maybe this will help: https://nx.dev/nx-api/esbuild/executors/esbuild#thirdparty

Try to set the thirdParty option to true and build again. It did the trick for me (after struggling for quite a while). As I understand it the option gives you more control about the bundling scope.

Your solution is amazing! After struggling with it for nearly 24 hours, I stumbled upon your trick and it worked like a charm. Thank you!