Search code examples
node.jsaws-lambdanode-modulesaws-cdk

How can I zip Node Lambda dependencies in AWS CDK stack?


I am using the CDK to create a simple serverless project with API Gateway, Lambda and DynamoDB. Seems pretty cool so far but I get the following error when I add an external dependency to the Lambda:

"Runtime.ImportModuleError: Error: Cannot find module './uuid-random'",

For clarity, I'm not asking what the problem is with this error, as that is well documented. I'm looking for help as my attempts to zip the dependencies have failed so far.

I have done my research, and I am not alone in this scenario. However, I'm a little confused with what path to take. I need to bundle my dependencies but all of the examples so far are fairly complex for what I am doing, and none of the examples fit. I have also seen suggestions of using fromAsset, but that didnt work either (cdk deploy just hung). So, I'd really appreciate any help in getting past this seemingly simple issue. TIA.

Project structure:

bin/
  cdkProject.js
handlers/
  api.js
lib/
  cdkProject-stack.js
node_modules/
test/
.gitignore
cdk.json
package.json
tsconfig.json

Lambda (api.js)

const AWS = require("aws-sdk");
const db = new AWS.DynamoDB;
const TABLE_NAME = process.env.TABLE_NAME || "";
const PRIMARY_KEY = process.env.PRIMARY_KEY || "";
const uuid = require('./uuid-random');

async function postProduct(event) {

  const params = {
    TableName: TABLE_NAME,
    Item: {
      "id": {
        S: uuid()
      },
      "name": {
        S: "Test Product 1"
      },
      "price": {
        N: "1.55"
      },
      "tags": {
        SS: [ "tag1","tag2" ] 
      } 
    }
  };

  try {
    const response = await db 
      .putItem(params)
      .promise()
      .then(res => res)
      .catch(err => err);
    console.log(JSON.stringify(response, undefined, 2));
    return JSON.stringify(response, undefined, 2)
  } catch (err) {
    console.log(JSON.stringify(err, undefined, 2));
  }
}

module.exports = {
  postProduct
}

Solution

  • Ideally each lambda needs its own package.json which contains its own dependencies.

    enter image description here

    cdk code will refer it to the lambda folder as

    const fn = new lambda.Function(this, "MyFunction", {
      runtime: lambda.Runtime.NODEJS_12_X,
      handler: "index.handler",
      code: lambda.Code.fromAsset(path.join("./handlers/test-uuid/")),
    });