aws / aws-cdk

The AWS Cloud Development Kit is a framework for defining cloud infrastructure in code
https://aws.amazon.com/cdk
Apache License 2.0
11.57k stars 3.88k forks source link

aws-lambda-nodejs: How to setup AWS CDK to use ESM with layers / top level await #23333

Open pfried opened 1 year ago

pfried commented 1 year ago

Describe the issue

Lambda is one of the most important services of the AWS portfolio. Significant improvements have been made allowing the NodeJS runtime (14+) to use ESM and top level await:

  1. ESM Announcement Top Level Await
  2. NodeJS 18 Annoucement
  3. NodeJS 18 Blog Post (aws-cdk_v3, ESM via NODE_PATH, global fetch, ...)

Yet I cannot really use that in my application due to several reasons:

  1. Lambda Layers are a de facto requirement for most bigger applications. Before the NodeJS 18 release there was no support for ESM Lambda Layers. I have not checked if the new

    Support for ES module resolution using NODE_PATH

solves this issue since I did not test it ever since. Has anyone?

  1. When having CDK project files with the lambda function handler code side by side in a project you will have issues with typechecking since the .tsconfig file shipped with aws-cdk does not play nice with handler code which needs other settings in .tsconfig. On the other hand if you change your .tsconfig file to other target/module/library settings the project will fail (no module errors, if you change package.json to "type"="module" it will not like the*.ts` extension, etc. etc. its a rabbit hole to which bottom I never got)

  2. The state of Lambda Layer bundling is a wild landscape of self-baked solutions (of course I have my own). The issues of this are widespread and maybe better in its own thread)

I would heavily welcome if someone at AWS / AWS-CDK takes a deep dive on how to setup an aws-cdk TypeScript project with ESM / top level await / ESM layers and shows it to the rest of the world. There is too much potential improvement on the line to keep this lingering in its current state (is it only the docs?)

The whole JavaScript ecosystem with CJS / ESM etc. is a mess only few developers will fully understand (excluding me). AWS-CDK is a powerful but complex software (which I love). Implementing the above requires a lot of knowledge (at least when the solution must be compatible with future plans / releases)

Related Issues:

  1. https://github.com/aws/aws-appsync-community/issues/213
  2. https://github.com/aws/aws-cdk/issues/21635
  3. https://github.com/aws/aws-cdk/issues/21329
  4. https://github.com/aws/aws-sdk-js-v3/issues/3386
  5. https://github.com/aws/aws-lambda-nodejs-runtime-interface-client/issues/93#issuecomment-2042201321
Partial solutions / approaches to some problems and additional content 1. https://github.com/coderbyheart/aws-lambda-esm-with-layer 2. https://github.com/vibe/aws-esm-modules-layer-support 3. https://twitter.com/adamdotdev/status/1523282408417677312 + https://github.com/adamelmore/cdk-top-level-await 4. https://github.com/huntharo/lambda-docker-typescript-esm

Links

https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda_nodejs-readme.html

revmischa commented 1 year ago

I have a CDK Severless-Stack project template that uses ESM and top-level await here: https://github.com/jetbridge/sst-prisma It has layers (prisma and sharp for nextjs) that are CJS but are loaded fine by ESM lambda functions with the use of a goofy compat shim

pfried commented 1 year ago

I created a repository here: https://github.com/Nantis-GmbH/cdk-lambda-with-layers to show my approach to lambda and layer bundling.

Short summary:

Downsides:

otterley commented 1 year ago

Just FYI, our use of the / separator in our Construct Library packages causes issues with some linters, namely, es-lint-plugin-n (see https://github.com/eslint-community/eslint-plugin-n/issues/21)

daveharig commented 11 months ago

Confirmed w/ AWS support

1) CDK and Lambda Node 16+ w/ Top level Await are both supported features of AWS.

2) They can't be used together at the same time.

3) The service team has known about the issue for almost a year.

4) They have yet to provide a workaround.

I'll keep requesting escalations w/ AWS Support until I get a solution worth reporting back with.

mrgrain commented 11 months ago

@daveharig Did you mean to mention layers somewhere in your list?

daveharig commented 11 months ago

The issue is bigger than Layers. It's any TS CDK project with any Lambda wanting to use ESM at the same time. This Layers case was just the first one to discover it and publicly post about it. This guy sums up the broader issue really well. https://twitter.com/adamdotdev/status/1523282408417677312?s=20

mrgrain commented 11 months ago

Thanks for the link @daveharig. Going by the video, this appears possible already (not the layers stuff maybe). I also agree with the OP that ESM vs CJS is a mess and hard to understand. Would you mind clarifying what your ask is specifically?

daveharig commented 11 months ago

The Twitter workaround is hack-y at best. Depending on the SDK's used in your Lambdas you end up chasing your tail even more.

My ask is that the CDK service team provide official documentation on how to support Lambda w/ ESM in a TS CDK project.

ThePlenkov commented 5 months ago

In my case I just changed to "app": "npx tsx src/bin/app.ts" and it just works. No need even to compile. Check what tsx project is.

github-actions[bot] commented 5 months ago

This issue has received a significant amount of attention so we are automatically upgrading its priority. A member of the community will see the re-prioritization and provide an update on the issue.

coderbyheart commented 5 months ago

@pfried can you add https://github.com/aws/aws-lambda-nodejs-runtime-interface-client/issues/93#issuecomment-2042201321 to your related issues?

daveharig commented 5 months ago

@ThePlenkov this allowed you to change to "type": "module" in your package.json and "target": "ESNext" "module": "ESNext" in your tsconfig.json?

ThePlenkov commented 5 months ago

Of course. Tsx doesn't care

daveharig commented 5 months ago

@ThePlenkov thank you! I'll give it a try.

pedroGenio commented 4 months ago

could anyone please clarify how to use TSX to get top level await working with Typescript and CDK ? I'm quite new to both and my setup is not working properly.

domengabrovsek commented 4 months ago

In my case I just changed to "app": "npx tsx src/bin/app.ts" and it just works. No need even to compile. Check what tsx project is.

This worked for me as well to deploy the cdk project. I haven't tried the top level await yet. I'll report how that goes.

daveharig commented 4 months ago

@domengabrovsek that is fantastic! Would you be willing to share how you have your compiler options set in tsconfig.json?

Phil1216 commented 3 months ago

I too have been down the ts-node rabbit hole. Apparently using "module": "ESNext" with ts-node requires esm, and the issue here https://github.com/TypeStrong/ts-node/issues/1997 suggests that using esm with ts-node is broken for newer versions of node.

When I switched to tsx, things started working.

cjnoname commented 2 weeks ago

swc-node will save your life