简体   繁体   中英

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
}

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

在此处输入图像描述

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/")),
});

Use the @aws-cdk/aws-lambda-nodejs construct, which will bundle your lambda code and all of the dependencies using esbuild.

By default the construct will use Docker version of esbuild. But if you explicitly add esbuild to your project deps, then it will use the local version and you won't need Docker.

Whenever creating a lambda function, you should make sure the folder containing the handler function has a package.json file if you imported external dependencies in your lambda handler function.

Then, in that folder you can run npm install to produce a node_modules folder with all the dependencies installed based on package.json

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

Finally, point your lambda.Code.fromAsset to the handlers folder.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM