AWS Logo
Menu
AWS CDK NodeJS Lambda Bundling

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

The Basics of CDK Bundling

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.

Understanding NodejsFunction Construct

Let's analyze a real-world example of a resize handler Lambda function:
Let's break down the key bundling-related properties:

1. Entry Point

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.

2. Bundling Configuration

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 Deep Dive

Why Docker Bundling?

Docker-based bundling is particularly important when:
  1. Your function uses native modules (like 'sharp') that need to be compiled for the Lambda runtime environment
  2. You need to ensure consistency between your development environment and the Lambda execution environment
  3. You want to guarantee that all dependencies are properly resolved and compiled

How Docker Bundling Works

When forceDockerBundling is set to true, the CDK follows this process:
  1. Creates a temporary Docker container based on the Lambda runtime image
  2. Mounts your source code directory into the container
  3. Installs dependencies and compiles native modules within the container
  4. Bundles everything using esbuild
  5. Outputs the bundled code to a directory that gets packaged into the Lambda deployment package

Example Lambda Function Code

Here's what the Lambda function code might look like:

Best Practices for Bundling

  1. 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
  2. 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
  3. 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
  4. 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

Troubleshooting Common Bundling Issues

  1. Docker-related Issues
    • Error: Failed to bundle asset ResizeHandler/Code/Stage...
    • Ensure Docker is running
    • Check Docker permissions
    • Verify sufficient disk space
  2. 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
  3. Bundle Size Issues
    • Use bundling.minify to reduce size
    • Consider splitting large functions
    • Review and optimize dependencies

Conclusion

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.
 

Comments