aws-cdk: (aws-lambda-nodejs): does not properly detect `esbuild` when used with Yarn 2+ in PnP mode

aws-cdk in general works properly with yarn 2+ in Plug’n’Play (PnP) mode. See https://yarnpkg.com/features/pnp

PnP mode does not use node_modules and thus npx cannot detect that esbuild is installed in the project, so this block of code fails:

https://github.com/aws/aws-cdk/blob/8f1cfe4087b765cecd3ceb01745167646d617fec/packages/%40aws-cdk/aws-lambda-nodejs/lib/util.ts#L115-L130

Also this block of code is problematic as well since it also uses npx: https://github.com/aws/aws-cdk/blob/8f1cfe4087b765cecd3ceb01745167646d617fec/packages/%40aws-cdk/aws-lambda-nodejs/lib/bundling.ts#L141-L158

Overall, spawning esbuild via its CLI seems far less than ideal. Instead, it should probably be executed via its nodejs api:

Example:

require('esbuild').buildSync({
  entryPoints: ['in.ts'],
  outfile: 'out.js',
})

Getting the installed version would be as easy as: require('esbuild/package.json').version

Reproduction Steps

mkdir test
yarn init -2
...set up cdk project...
yarn add esbuild

yarn cdk deploy '*'

Prints: esbuild cannot run locally. Switching to Docker bundling.

A workaround is possible by installing esbuild globally, but this is far from ideal.

What did you expect to happen?

esbuild should work properly

What actually happened?

esbuild cannot run locally. Switching to Docker bundling.

Environment

  • CDK CLI Version : 1.90.1
  • Framework Version: 1.90.1
  • Node.js Version: 15.9.0
  • OS : macOS
  • Language (Version): TypeScript 4.0.5

Other

Originally added in https://github.com/aws/aws-cdk/pull/11289 by @jogold


This is 🐛 Bug Report

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 3
  • Comments: 27 (17 by maintainers)

Commits related to this issue

Most upvoted comments

Just report I got error Command "esbuild" not found. under yarn v1.22.10 and cdk 1.106.1 (build c832c1b)

OK found the problem, will fix it.

Only happens when consuming a node module that uses a NodejsFunction.

Just got esbuild not found when using with pnpm workspace, any workaround?

Is it still non fixed? Have this issue with latest CDK for NodejsFunction

same

Hi @andreialecu

Thanks for the feedback.

Because the CDK uses jsii and the CDK team doesn’t currently want to bundle esbuild in the CDK we cannot use the Node.js API or declare esbuild as a peer dependency unfortunately.

We can however improve detection with Yarn v2. We could do yarn run esbuild --version when working with a yarn.lock. A similar approach can be used to run the esbuild CLI.

Did you run npm install -g esbuild? Esbuild needs to be installed using npm (not yarn) for the workaround to work.

it still wouldn’t really work for pnpm for example

No too familiar with pnpm but will have a look.

All package managers support optional peer dependencies:

Of course but with jsii you can only include a module as a peer dependency if it’s jsii-enabled. Otherwise you need to add it as a bundled dependency (which is what the CDK team doesn’t want for the moment).

@jogold yarn run esbuild would indeed work for yarn, but it still wouldn’t really work for pnpm for example. pnpm also supports the PnP installation mechanism: https://pnpm.js.org/blog/2020/10/17/node-modules-configuration-options-with-pnpm#plugnplay-the-strictest-configuration

Regarding peer dependencies, esbuild could be added as an optional peer dependency:

All package managers support optional peer dependencies:

https://docs.npmjs.com/cli/v7/configuring-npm/package-json#peerdependenciesmeta https://yarnpkg.com/configuration/manifest#peerDependenciesMeta https://pnpm.js.org/en/package_json#peerdependenciesmeta

Calling esbuild via its api would fully abstract this and make it package manager independent, meaning it should work with pnpm as well.