CDK NodejsFunction with Lambda Layer

0

I want to import node_modules in Lambda Layer in a Lambda function defined in CDK NodejsFunction.
Pass the deployed Lambda Layer's arn to NodejsFunction and execute cdk synth --no-staging before sam local invoke.
At this time, if the module you are importing in the Lambda function is not installed in the CDK node_modules, you will get a Could not resolve <module name> error.
So, if we install the module in the CDK node_modules (yarn add <module name>), the sam local invoke will seem to refer to the CDK node_modules instead of the layer.
How can I make the Lambda function reference the node_modules in the deployed layer instead of the node_modules in the CDK?

lambda-stack.ts

new lambda.NodejsFunction(this, 'ExportQuotationPDF', {
  runtime: Runtime.NODEJS_14_X,
  entry: 'lambda/export-quotation-pdf/index.ts',
  layers: [
    LayerVersion.fromLayerVersionArn(
      this,
      'layer:datefns',
      'arn:aws:lambda:ap-northeast-1:1234567890:layer:datefns:1
    )
  ]
})

lambda/sample-function/index.ts

// When I run cdk synth without running `yarn add data-fns`, it returns the following error
// Could not resolve "date-fns"
// But if I do `yarn add data-fns`,
// this function appears to reference the node_modules in the CDK, not the layers.
import { format } from 'date-fns'

export const handler = async () => {
  try {
    console.log(format(new Date(), "'Today is a' eeee"))
  } catch (error) {
    console.log(error)
  }
}
asked 2 years ago337 views
1 Answer
0

The concept of lambda layers will come into the picture only in AWS environment.

When you're testing locally, you can refer to the local package. However, you need to mention this package as external modules when bundling the lambda so that your lambda function will not bundle that package when deploying the lambda.

You would do something like this

const nodeJsFnProps: NodejsFunctionProps = {
      bundling: {
        externalModules: [
          'aws-sdk', // Use the 'aws-sdk' available in the Lambda runtime
         'date-fns',
        ],
      },
      runtime: Runtime.NODEJS_16_X,
      timeout: Duration.minutes(3),
      memorySize: 256,
    };

    const lambdaWithLayer = new NodejsFunction(this, 'lambdaWithLayer', {
      entry: path.join(__dirname, '../src/lambdas', 'lambda.ts'),
      ...nodeJsFnProps,
      functionName: 'lambdaWithLayer',
      handler: 'handler',
      layers: [logicLayer, utilsLayer],
    });

I've written a detailed step-by-step guide on lambda layers here - https://www.cloudtechsimplified.com/aws-lambda-layers/

answered a year ago

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions