Lambda层node_modules

xxe27gdn  于 2023-10-17  发布在  Node.js
关注(0)|答案(5)|浏览(150)

我正在创建一个lambda层,捆绑了一些依赖项,包括node_modules。我成功地创建了一个层,但当我试图从我的代码中请求一个模块时,控制台告诉我找不到该模块。这里是代码

var Promise = require('promise');
module.exports.handler = function(event, context, callback) {   
  new Promise(function (resolve, reject) {
    setTimeout(function() {
      callback(null, "helloWorld2");
    }, 9000);
  });
};

如何从层引用节点模块???

htzpubme

htzpubme1#

你是如何运行lambda的?如果通过sam cli,像下面这样的东西已经为我工作作为我的template.yaml.

示例模板

AWSTemplateFormatVersion: 2010-09-09
Transform: AWS::Serverless-2016-10-31
Description: example of node.js lambda function using layer for dependencies

Resources:

  ExampleFunction:
    Type: AWS::Serverless::Function
    Properties:
      Runtime: nodejs8.10
      CodeUri: nodejs/
      Handler: src/event.handler
      Layers:
        - !Ref NodeModulesLayer

  NodeModulesLayer:
    Type: AWS::Serverless::LayerVersion
    Properties:
      Description: full set of function dependencies
      ContentUri: ./
      CompatibleRuntimes:
        - nodejs6.10
        - nodejs8.10
      LicenseInfo: 'Available under the MIT-0 license.'
      RetentionPolicy: Retain

指向本地层

SAM开发人员指南包括一个关于Working with Layers的页面。在我写这篇文章的时候,他们并没有真正进入如何引用本地文件路径中的层,而是专注于对远程托管层的引用。
我发现棘手的方面是,node.js层的目录结构应该是...

nodejs/
  node_modules/

.这意味着为了使本地安装的node_modules目录作为层工作,您的package.json文件必须嵌套在名为nodejs的文件夹中。
注意上面例子template.yaml中的路径:

  1. ExampleFunction.Properties.CodeUri设置为nodejs/
  2. ExampleFunction.Properties.Handler应该设置为处理程序文件的路径,相对于nodejs/
  3. NodeModulesLayer.Properties.ContentUri设置为包含template.yaml文件和nodejs目录的文件夹。
    这意味着我的例子假设以下结构...
nodejs/
  node_modules/
  src/
    event.js
  package.json
template.yaml

保留sam构建支持

另一个需要警惕的问题是...
关于在template.yaml中定义函数资源,在CodeUriHandler中放置路径的哪些部分方面有一些“灵活性”。在某些情况下,做…

Properties:
      CodeUri: nodejs/src/
      Handler: event.handler

......就像做......

Properties:
      CodeUri: nodejs/
      Handler: src/event.handler

但是,如果你使用sam build命令,前者将不工作。该命令期望在CodeUri目录中找到package.json。因此,请继续使用CodeUri: nodejs/,并使用Handler值来导航访问处理程序所需的任何其他文件夹层次结构。

ut6juiuv

ut6juiuv3#

2022年的毕业典礼...

我很难弄清楚,这是否仍然是最先进的,或者我们现在可以简化依赖关系。**事实证明,现在可以在没有黑客或复杂设置的情况下包含依赖项。
对我来说,用new lambda.NodeJsFunction()而不是new lambda.Function()创建lambda就可以了。然而,我很难找到一个工作样本。我决定和你分享一个样本回购。

示例仓库

https://github.com/AntoniusGolly/cdk-lambda-typescript-boilerplate
它的作用:

  • 它有很多你不需要的东西来证明它的目的(例如,它基于config.ts生成一个API网关,因此如果不需要,请忽略该部分)
  • 它允许您使用TS和ES6
  • 它允许您使用依赖项:也就是说,我在这里使用node-fetch
  • 我只做cdk deploy,没有其他捆绑
  • 根据docu,默认情况下,除了aws-sdk之外,所有节点模块都是捆绑的。
  • 我不知道它是如何工作的,但它确实如此;)

我希望这能帮助一些人,因为我会感激它。

tjjdgumg

tjjdgumg4#

为了给你的模块寻址,你必须使用path和'/opt'作为前缀。
如果这是你的文件,你打包到myLib.zipmyLib.js内,你应该写:

const myModule = require('/opt/myLib');

如果你插入已安装的依赖项,那么你上传node_modules.zipnode_modules文件夹和地址:

const module = require('/opt/node_modules/lib_name');
sqxo8psd

sqxo8psd5#

我发现最简单的方法是在运行时运行ls命令

const fs = require('fs');

exports.handler = async (event, context) => {
    const layerDirectory = '/opt'; // Replace with the actual path to the Layer directory

    try {
        const files = fs.readdirSync(layerDirectory);
        console.log('Contents of the Lambda Layer directory:');
        files.forEach((file) => {
            console.log(file);
        });
    } catch (error) {
        console.error('Error listing the directory:', error);
    }

    // Your Lambda function code here
};

输出

Function Logs
START RequestId: ff8d6039-78f5-46c8-a151-7a6da51404c9 Version: $LATEST
2023-10-11T16:49:56.045Z    ff8d6039-78f5-46c8-a151-7a6da51404c9    INFO    Contents of the Lambda Layer directory:
2023-10-11T16:49:56.045Z    ff8d6039-78f5-46c8-a151-7a6da51404c9    INFO    node_modules
2023-10-11T16:49:56.054Z    ff8d6039-78f5-46c8-a151-7a6da51404c9    INFO    package-lock.json
2023-10-11T16:49:56.054Z    ff8d6039-78f5-46c8-a151-7a6da51404c9    INFO    package.json
END RequestId: ff8d6039-78f5-46c8-a151-7a6da51404c9
REPORT RequestId: ff8d6039-78f5-46c8-a151-7a6da51404c9  Duration: 11.99 ms  Billed Duration: 12 ms  Memory Size: 128 MB Max Memory Used: 67 MB  Init Duration: 163.70 ms

在这里,您可以看到文件直接部署在/opt下的node_modules中,因此在我的示例中,这里是工作的import语句

const axios = require('/opt/node_modules/axios');

相关问题