CDK Construct to build Node.js AWS lambdas using webpack
Table of contents:
yarn add aws-lambda-nodejs-webpack
// infra/super-app-stack.js
const sns = require("@aws-cdk/aws-sns");
const subscriptions = require("@aws-cdk/aws-sns-subscriptions");
const core = require("@aws-cdk/core");
const { NodejsFunction } = require("aws-lambda-nodejs-webpack");
module.exports = class SuperAppProductionStack extends core.Stack {
constructor(scope, id, props) {
super(scope, id, props);
const slackNotificationsLambda = new NodejsFunction(
this,
"slack-notifications-lambda",
{
entry: "events/slack-notifications.js", // required
},
);
}
};
// events/slack-notifications.js
import { WebClient as SlackWebClient } from "@slack/web-api";
export function handler(event) {
const message = event.Records[0].Sns.Message;
// do something with message
}
- fast, no-docker CDK construct
- lambda output respects original files structure and node_modules (no inlining)
- lambda output only contains the necessary files, no README, tests, ...
- bundling happens in temporary directories, it never writes in your project directory
- source map support
There's already a dedicated aws-lambda-nodejs module for CDK but I had two major issues with it:
- CDK uses docker for anything lambda build related. This means it mounts your whole Node.js project (not just the lambda code) inside Docker before running a bundler like Parcel. This is perfectly fine and performant on Linux and Windows, but this is extremely slow on macOS: a single cdk synth would take 2 minutes for a 3 lines lambda. Since it might take a very long time for Docker on macOS to get as fast as on Linux. Even their latest update (mutagen), while significantly faster, still takes 20s just to mount a Node.js project.
- aws-lambda-nodejs generates a single file bundle with every local and external module inlined. Which makes it very hard to debug and read on the AWS console. I wanted a lambda output that mimicks my project file organization.
I want to be clear: I respect a LOT the work of the CDK team, and especially @jogold, author of aws-lambda-nodejs) that helped me a lot into debugging performance issues and explaining to me how everything works.
This is a list of features I thought could be interesting to users. If you need on of them, please contribute to the project.
- Test/Get feedback on TypeScript support
- Get feedback on monorepo support
- Allow passing webpack/babel options/a function that can update the full webpack configuration
- Allow native modules/passing externals, with option
nativeModules
orexternals
. They would have to be installed into a temp folder withnpm_config_arch
andnpm_config_platform
and aliased in webpack configuration/or considered as externals. Externals and nativeModules seems related options but may be completely different - Use jsii to build the construct for other languages
- Add tests
- (if current way buggy): force people to provide aliases instead of considering cwd as base node_module
- Allow usage without the need of
entry
:new NodejsFunction(this, "slack-notifications-lambda");
that would mimic https://docs.aws.amazon.com/cdk/api/latest/docs/aws-lambda-nodejs-readme.html#nodejs-function - [ ]
- Generate a bundle where entry is moved to /main.js
- Allow using TypeScript
- use webpack and babel cache
- remove webpackconfig from bundle
- pass runtime to babel target
- cdk synth generates different builds even when the lambda code does not changes, issue?
- Allow using babel, if you need preset-env
- add babel preset env by default
-
add bundling timing information to output consolenote: this would pollute cdk synth -
Ask CDK team if this could live under their repositoriesBetter be just community based - Other ideas? Open an issue
// fork and clone
cd aws-lambda-nodejs-webpack
yarn
yarn link
yarn start
# in another terminal and project where you want to test changes
yarn link aws-lambda-nodejs-webpack
# cdk commands will now use your local aws-lambda-nodejs-webpack
- the CDK team for this awesome project
- @jogold for his time while helping me debugging performance issues on Docker