在 NodeJS lambda 中使用自定义层

问题描述 投票:0回答:3

尝试将图层导入 lambda 函数时出现错误。 我已经检查了所有设置和配置,但我只是不明白为什么当我的函数部署并运行时,我收到来自 AWS 的错误,说它无法找到

layers
层:

{
    "errorType": "Error",
    "errorMessage": "Cannot find module 'layers'\nRequire stack:\n- /var/task/entities/transakWebhookEvent.js\n- /var/task/handler.js\n- /var/task/s_money_movements_api.js\n- /var/runtime/UserFunction.js\n- /var/runtime/index.js",
    "code": "MODULE_NOT_FOUND",
    "requireStack": [
        "/var/task/entities/transakWebhookEvent.js",
        "/var/task/handler.js",
        "/var/task/s_money_movements_api.js",
        "/var/runtime/UserFunction.js",
        "/var/runtime/index.js"
    ],
    "stack": [
        "Error: Cannot find module 'layers'",
        "Require stack:",
        "- /var/task/entities/transakWebhookEvent.js",
        "- /var/task/handler.js",
        "- /var/task/s_money_movements_api.js",
        "- /var/runtime/UserFunction.js",
        "- /var/runtime/index.js",
        "    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:815:15)",
        "    at Module._require.i.require (/var/task/serverless_sdk/index.js:9:73131)",
        "    at require (internal/modules/cjs/helpers.js:74:18)",
        "    at Object.<anonymous> (/var/task/entities/transakWebhookEvent.js:5:20)",
        "    at Module._compile (internal/modules/cjs/loader.js:999:30)",
        "    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1027:10)",
        "    at Module.load (internal/modules/cjs/loader.js:863:32)",
        "    at Function.Module._load (internal/modules/cjs/loader.js:708:14)",
        "    at Module.require (internal/modules/cjs/loader.js:887:19)",
        "    at Module._require.i.require (/var/task/serverless_sdk/index.js:9:73397)"
    ]
}

我正在使用无服务器框架来管理 lambda 和层的部署。

我的项目是这样设置的:

05-24 07:12PM ~/poc $ ls
README.md  webapp-display  webapp-layers  webapp-money-movements  webapp-signup

我的图层位于具有以下文件夹结构的单独文件夹中:

05-24 07:09PM ~/poc/webapp-layers $ ls
index.js  layers  node_modules  package-lock.json  package.json  serverless.yml

我尝试使用我的图层的模块位于此文件夹结构中:

05-24 07:10PM ~/poc/webapp-money-movements $ ls
entities  handler.js  node_modules  package-lock.json  package.json  prettier.config.js  serverless.yml

我的 lambda 模块的 package.json 引用如下层:

 {
  "name": "webapp-money-movements",
  "version": "1.0.0",
  "description": "",
  "dependencies": {
    "bcrypt": "^5.0.1",
    "express": "^4.17.1",
    "jsonwebtoken": "^8.5.1",
    "serverless-domain-manager": "^5.1.0",
    "serverless-http": "^2.7.0",
    "serverless-plugin-git-variables": "^5.1.0",
    "uuid": "^8.3.2"
  },
  "devDependencies": {
    "@serverless/eslint-config": "^3.0.0",
    "eslint": "^7.22.0",
    "eslint-config-strongloop": "^2.1.0",
    "eslint-plugin-import": "^2.22.1",
    "git-list-updated": "^1.2.1",
    "prettier": "^2.2.1",
    "layers": "file:../webapp-layers"
  },
  "eslintConfig": {
    "extends": "@serverless/eslint-config/node",
    "root": true
  },
  "scripts": {
    "lint": "eslint  --ignore-path .gitignore .",
    "lint:updated": "pipe-git-updated --ext=js -- eslint --ignore-path .gitignore",
    "prettier-check": "prettier -c --ignore-path .gitignore \"**/*.{css,html,js,json,md,yaml,yml}\"",
    "prettier-check:updated": "pipe-git-updated --ext=css --ext=html --ext=js --ext=json --ext=md --ext=yaml --ext=yml -- prettier -c",
    "prettify": "prettier --write --ignore-path .gitignore \"**/*.{css,html,js,json,md,yaml,yml}\"",
    "prettify:updated": "pipe-git-updated --ext=css --ext=html --ext=js --ext=json --ext=md --ext=yaml --ext=yml -- prettier --write"
  }
}

我的 lambda 函数的 serverless.yml 设置如下:

org: rt
app: poc
service: poc-money-movements

frameworkVersion: '2'

custom:
  tableNameDeposits: 'deposits-table-${self:provider.stage}'
  tableNameWithdrawalRequests: 'withdrawal-request-table-${self:provider.stage}'
  tableFundingAccountTransactions: 'funding-account-transaction-table-${self:provider.stage}'
  defaultRegion: eu-west-2
  [...]
  customStage:
    prod: prod
    staging: staging
    dev: dev
  [...]

plugins:
  - serverless-domain-manager

provider:
  name: aws
  runtime: nodejs12.x
  lambdaHashingVersion: '20201221'
  stage: ${self:custom.customStage.${opt:stage, 'dev'}, self:custom.customStage.dev}
  region: ${opt:region, self:custom.defaultRegion}
  profile: rt-${self:provider.stage}
  apiGateway:
    shouldStartNameWithService: true
  environment:
    WITHDRAWAL_REQUEST_TABLE: ${self:custom.tableNameWithdrawalRequests}
    DEPOSITS_TABLE: ${self:custom.tableNameDeposits}
    FUNDING_ACCOUNT_TRANSACTION: ${self:custom.tableFundingAccountTransactions}
  iam:
    role:
      statements:
        [...]
  

functions:
  money-movements-api:
    handler: handler.handler
    layers:
      - ${cf:poc-layers-${self:provider.stage}.AccountsLambdaLayerQualifiedArn}
    description: All endpoints needed for users to move money
    events:
      - http: ANY /
      - http: 'ANY /{proxy+}'

这是我尝试在 Nodejs lambda 函数中导入图层的方法:

// Load the AWS SDK for JS
const AWS = require("aws-sdk");
AWS.config.update({region: 'eu-west-2'});
const jwt = require('jsonwebtoken');
const {accounts} = require("layers");

module.exports.new = async function(body) {
    let order = transakWebhook(body)
    console.log("order: ", order)

    const account = new accounts(order.partnerCustomerId)
[...]

我的图层模块的

package.json
是这样设置的

{
  "name": "webapp-layers",
  "version": "1.0.0",
  "description": "AWS Lambda Layers for Node.js",
  "main": "index.js",
  "scripts": {
    "compile": "tsc",
    "compile:watch": "npm run compile -- --watch"
  },
  "author": "Remi Tuyaerts",
  "license": "ISC",
  "dependencies": {
    "@middy/core": "^1.5.2",
    "@onfido/api": "^1.5.4",
    "auth0": "2.29.0",
    "awilix": "^4.3.3",
    "aws-sdk": "2.813.0",
    "compose-function": "^3.0.3",
    "date-fns": "2.16.1",
    "dotenv": "8.2.0",
    "ejs": "3.1.5",
    "fs-extra": "^9.1.0",
    "html-pdf": "2.2.0",
    "http-status": "^1.5.0",
    "joi": "17.2.1",
    "jsdom": "16.4.0",
    "knex": "0.21.14",
    "moment": "2.28.0",
    "node-fetch": "2.6.1",
    "nodemailer": "^6.4.17",
    "pg": "^8.4.2",
    "reflect-metadata": "^0.1.13",
    "typeorm": "^0.2.31",
    "winston": "3.3.3"
  },
  "devDependencies": {
    "@types/auth0": "^2.33.2",
    "@types/aws-lambda": "^8.10.72",
    "@types/jsdom": "^16.2.7",
    "@types/node": "^14.14.34",
    "@types/node-fetch": "^2.5.8",
    "@types/nodemailer": "^6.4.1",
    "typescript": "4.2.3"
  }
}

我的层的其他 serverless.yml 设置如下:

org: rt
app: poc
service: poc-layers

provider:
  name: aws
  runtime: nodejs12.x
  lambdaHashingVersion: 20201221
  versionFunctions: false
  stage: ${self:custom.customStage.${opt:stage, 'dev'}, self:custom.customStage.dev}
  region: eu-west-2
  environment:
    STAGE: ${self:provider.stage}

custom:
  tableNameDeposits: 'deposits-table-${self:provider.stage}'
  tableNameWithdrawalRequests: 'withdrawal-request-table-${self:provider.stage}'
  tableFundingAccountTransactions: 'funding-account-transaction-table-${self:provider.stage}'
  customStage:
    prod: prod
    staging: staging
    dev: dev

layers:
  accounts:
    name: accounts
    path: layers/
    retain: true

我的

accounts.js
文件夹中的
./webapp-layers/layers/
设置如下:

const AWS = require("aws-sdk");
AWS.config.update({region: 'eu-west-2'});

const { v4: uuidv4 } = require('uuid');

// Create the DynamoDB Document Client
var dynamodb = new AWS.DynamoDB.DocumentClient();
var tableName = process.env.DEPOSITS_TABLE;

class accounts {
    constructor(userId) {
        this.userId = userId
    }
    
[...]

module.exports = { accounts };

我还将我的图层导出到

index.js
根部的
./webapp-layers/
中,如下所示:

"use strict";
const accounts = require("./layers/accounts");
exports.accounts = accounts;
node.js amazon-web-services serverless layer
3个回答
7
投票

首先,关于层文件夹结构,所有共享文件都必须存储在nodejs文件夹下。这意味着,您的

layer
将如下所示:

05-24 07:09PM ~/poc/webapp-layers $ ls index.js 层 node_modules package-lock.json package.json serverless.yml

~/poc/webapp-layers $ tree
...
layers/
   nodejs/
      accounts/
         index.js
...

但是,使用上述结构,您必须更新 lambda 函数以需要

accounts
模块

const accounts = require("/opt/nodejs/accounts");

如果你想使用

const { accounts } = require("layers");

结构应该是:

~/poc/webapp-layers $ tree
...
layers/
   nodejs/
      node_modules/   <---------------
          layer/
             index.js
      accounts/
         index.js

并且

layer/index.js
只需重新导出
accounts
模块

"use strict";
const accounts = require("../accounts");
exports.accounts = accounts;

0
投票

错误消息显示找不到图层模块。

在你的代码中,有

const {accounts} = require("layers");
这意味着它是从node_modules导入的,但是在你的package.json中,没有layers包。因此,对于自定义创建的模块,您应该将其更改为
require("./layers")

我认为这会对您的问题有所帮助。


0
投票

做过这样的事

图层文件夹结构

nodejs/node_modules/handlebars

Lambda 代码

let handlebars;

if (process.env["AWS_LAMBDA_FUNCTION_NAME"] || process.env["AWS_EXECUTION_ENV"]) {
   handlebars = require("/opt/nodejs/node_modules/handlebars");
} else {
   handlebars = require("handlebars");
}
© www.soinside.com 2019 - 2024. All rights reserved.