Last updated: Jan 27, 2024
Reading timeยท4 min

We write our CDK code using TypeScript, so it makes sense to also write our Lambda code in TypeScript.
Nodejs doesn't natively support TypeScript, so we have to first compile our TypeScript code to JavaScript before we can deploy our Lambda functions.
In order to write a Lambda function in TypeScript and provision it with CDK, we have to use the NodejsFunction construct, which uses esbuild to automatically transpile and bundle our code.
Let's define the infrastructure for our function using CDK.
import * as cdk from 'aws-cdk-lib'; import {NodejsFunction} from 'aws-cdk-lib/aws-lambda-nodejs'; import * as lambda from 'aws-cdk-lib/aws-lambda'; import * as path from 'path'; export class CdkStarterStack extends cdk.Stack { constructor(scope: cdk.App, id: string, props?: cdk.StackProps) { super(scope, id, props); const myFunction = new NodejsFunction(this, 'my-function', { memorySize: 1024, timeout: cdk.Duration.seconds(5), runtime: lambda.Runtime.NODEJS_18_X, handler: 'main', entry: path.join(__dirname, `/../src/my-lambda/index.ts`), }); } }
Let's go over the code:
We have a CDK stack that provisions a single Lambda function.
The Lambda function uses the NodejsFunction construct which automatically transpiles and bundles our code, regardless if it's written in JavaScript or TypeScript.
The entry prop we passed to the function constructor is a path to the Lambda
function's code on the local file system. The entry prop supports files with
.js, .jsx, .ts and .tsx extensions.
The other props we passed to the NodejsFunction constructor are the same
props the generic
Function
construct supports.
In order to avoid unnecessary distractions, our function code will be very simple.
import {APIGatewayProxyEventV2, APIGatewayProxyResultV2} from 'aws-lambda'; export async function main( event: APIGatewayProxyEventV2, ): Promise<APIGatewayProxyResultV2> { console.log('event ๐', event); return { body: JSON.stringify({message: 'Successful lambda invocation'}), statusCode: 200, }; }
We defined a simple lambda function, in which we've typed the event and the response.
Our CDK code gets compiled down to CloudFormation before a deployment.
cdk.out directory. This is also where the asset files for our Lambda functions are stored.Let's run the synth command to generate the Lambda assets.
npx aws-cdk synth
If we now take a look at the assets folder in the cdk.out directory, we can
see that our Lambda function's code has been compiled down to JavaScript.

At this point, we are ready to deploy our stack.
npx aws-cdk deploy
Now that the Lambda function has been successfully deployed, we can run a quick test using the Lambda console.

At this point, we've successfully invoked a Lambda function that we wrote using TypeScript and provisioned via AWS CDK.
The
NodejsFunction
construct uses esbuild under the hood to automatically transpile and bundle
our code.
We can reduce the bundle size of our Lambda functions by setting the minify
property to true in the props object of the NodejsFunction.
const myFunction = new NodejsFunction(this, 'my-function', { // ...rest // ๐ bundling: { minify: true, externalModules: ['aws-sdk'], }, });
We've set the minify and externalModules options on the bundling,
property:
minify is a boolean that allows us to specify whether we want to minify
the code of our Lambda function. This enables us to decrease bundle size and
improve performance for larger functions.
externalModules is a string array that allows us to specify which modules
should NOT be bundled with our Lambda code. This enables us to exclude
modules that are already available in the Lambda runtime - for instance
aws-sdk and layers.
For example, if you used an npm package
called yup as a Lambda layer, you would add
the string yup to the externalModules array because layers are already
available in the Lambda environment.
I'll now run the synth command to inspect the output.
npx aws-cdk synth
If I open the cdk.out directory and look at the lambda asset, we can see that
it has been minified and is a one-liner.

The esbuild library is written in Golang and is way faster than any other
bundler I've ever used, so deployments for medium-sized projects go relatively
quick. Look at the speed comparison to other
bundlers.
The best thing about this approach is that we don't have to manage Webpack configurations and have our dependencies break every 2-3 months.
To delete the stack from your account, run the
destroy command.
npx aws-cdk destroy
We managed to use esbuild to write Lambda functions in Typescript. Now all of
our code, including the infrastructure, is written using the same language.
I've also written an article on how to provision lambda functions in CDK without using TypeScript.
You can learn more about the related topics by checking out the following tutorials: