
AWS CDK NodeJS Lambda Bundling
We'll explore how the AWS CDK handles bundling, with a special focus on the NodejsFunction construct and Docker-based bundling.
Published Jan 21, 2025
Bundling is the process of packaging your Lambda function code along with its dependencies into a deployment package that can be executed in the Lambda environment. The AWS CDK provides several bundling options, with the NodejsFunction construct offering particularly sophisticated bundling capabilities.
Let's analyze a real-world example of a resize handler Lambda function:
Let's break down the key bundling-related properties:
The
entry
property specifies the path to your Lambda function's source code. The NodejsFunction construct will use this as the starting point for the bundling process.This is where the magic happens. The bundling property accepts several options that control how your function is packaged:
nodeModules
: Lists dependencies that should be included in the bundle without being transformed by esbuild. This is crucial for native modules like 'sharp'.forceDockerBundling
: Forces the bundling process to use Docker, which is essential for native modules that need to be compiled for the Lambda environment.
Docker-based bundling is particularly important when:
- Your function uses native modules (like 'sharp') that need to be compiled for the Lambda runtime environment
- You need to ensure consistency between your development environment and the Lambda execution environment
- You want to guarantee that all dependencies are properly resolved and compiled
When
forceDockerBundling
is set to true, the CDK follows this process:- Creates a temporary Docker container based on the Lambda runtime image
- Mounts your source code directory into the container
- Installs dependencies and compiles native modules within the container
- Bundles everything using esbuild
- Outputs the bundled code to a directory that gets packaged into the Lambda deployment package
Here's what the Lambda function code might look like:
- Native Modules
- Always use
forceDockerBundling: true
when working with native modules - Include native modules in the
nodeModules
array to prevent esbuild from trying to bundle them
- Dependencies Management
- Keep your
nodeModules
list minimal - only include packages that actually need special bundling - Use the
external
property to exclude modules available in the Lambda runtime
- Performance Optimization
- Consider using
minify: true
to reduce bundle size - Use
sourcemap: true
during development for better debugging - Configure
tsconfig
properly to optimize TypeScript compilation
- Docker Configuration
- Ensure Docker is running when using
forceDockerBundling
- Consider using custom Docker images via
bundling.dockerImage
for specialized requirements - Use
bundling.environment
to pass environment variables to the Docker bundling process
- Docker-related Issues
Error: Failed to bundle asset ResizeHandler/Code/Stage...
- Ensure Docker is running
- Check Docker permissions
- Verify sufficient disk space
- Native Module Compilation Failures
- Verify the module is listed in
nodeModules
- Check if the module is compatible with the chosen Lambda runtime
- Examine Docker logs for compilation errors
- Bundle Size Issues
- Use
bundling.minify
to reduce size - Consider splitting large functions
- Review and optimize dependencies
Understanding CDK bundling is crucial for developing robust Lambda functions, especially when working with native modules. The NodejsFunction construct, combined with Docker-based bundling, provides a powerful and flexible way to package your Lambda functions correctly.
Remember to always test your bundled functions thoroughly, as the development environment might differ from the bundling environment. Using Docker-based bundling helps minimize these differences and ensures your functions work consistently in production.