简体   繁体   English

AWS Lambda 打包依赖

[英]AWS Lambda packaging with dependencies

Further outlining is in the context of NodeJS and Monorepo (based on Lerna).进一步概述是在 NodeJS 和 Monorepo(基于 Lerna)的上下文中。

I have AWS stack with several AWS Lambda inside deployed by means of AWS CloudFormation.我有 AWS 堆栈,里面有几个 AWS Lambda,是通过 AWS CloudFormation 部署的。 Some of the lambdas are simple (the single small module) and could be inlined:一些 lambda 很简单(单个小模块)并且可以内联:

https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-lambda.Code.html#static-from-wbr-inlinecode https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-lambda.Code.html#static-from-wbr-inlinecode

const someLambda = new Function(this, 'some-lambda', {
  code: Code.fromInline(fs.readFileSync(require.resolve(<relative path to lambda module>), 'utf-8')),
  handler: 'index.handler',
  runtime: Runtime.NODEJS_12_X
});

Some have no dependencies and packaged as follows:有的没有依赖,打包如下:

const someLambda = new Function(this, 'some-lambda', {
  code: Code.fromAsset(<relative path to folder with lambda>),
  handler: 'index.handler',
  runtime: Runtime.NODEJS_12_X
});

But in case of relatively huge lambdas with dependencies, as I understand, we only way to package (proposed by API) is @aws-cdk/aws-lambda-nodejs :但据我所知,如果 lambda 具有相对较大的依赖性,我们到 package(由 API 提议)的唯一方法是@aws-cdk/aws-lambda-nodejs

import * as lambdaNJS from "@aws-cdk/aws-lambda-nodejs";

export function createNodeJSFunction(
  scope: cdk.Construct, id: string, nodejsFunctionProps: Partial<NodejsFunctionProps>
) {
  const params: NodejsFunctionProps = Object.assign({
    parcelEnvironment: { NODE_ENV: 'production' },
  }, nodejsFunctionProps);

  return new lambdaNJS.NodejsFunction(scope, id, params);
}

For standalone packages, it works well, but in case of the monorepo it just hangs on synth of the stack.对于独立包,它运行良好,但在 monorepo 的情况下,它只是挂在堆栈的synth上。 I just looking for alternatives, cause I believe it is not a good idea to bundle ( parcel ) BE sources.我只是在寻找替代方案,因为我认为捆绑( parcel )BE 源不是一个好主意。

I've created the following primitive library to zip only required node_modules despite packages hoisting .我已经创建了以下原始库到zip只需要node_modules尽管包hoisting

https://github.com/redneckz/slice-node-modules https://github.com/redneckz/slice-node-modules

Usage (from monorepo root):用法(来自 monorepo 根目录):

$ npx @redneckz/slice-node-modules \
  -e packages/some-lambda/lib/index.js \
  --exclude 'aws-*' \
  --zip some-lambda.zip

--exclude 'aws-*' - AWS runtime is included by default, so no need to package it. --exclude 'aws-*' - 默认包含 AWS 运行时,因此无需 package。

Here is an example if using cloudformation and template.yml .这是使用cloudformationtemplate.yml的示例。

Create a make file: Makefile with following targets创建一个 make 文件: Makefile具有以下目标

# Application
APPLICATION=applicatin-name

# AWS
PROFILE=your-profile
REGION=us-east-1
S3_BUCKET=${APPLICATION}-deploy

install:
    rm -rf node_modules
    npm install

clean:
    rm -rf build

build: clean
    mkdir build
    zip -qr build/package.zip src node_modules
    ls -lah build/package.*

deploy:
    sam package \
        --profile ${PROFILE} \
        --region ${REGION} \
        --template-file template.yaml \
        --s3-bucket ${S3_BUCKET} \
        --output-template-file ./build/package.yaml

    sam deploy \
    --profile ${PROFILE} \
    --region ${REGION} \
    --template-file ./build/package.yaml \
    --stack-name ${APPLICATION}-lambda \
    --capabilities CAPABILITY_NAMED_IAM

Make sure the s3 bucket is created, you could add this step as another target in the Makefile.确保创建了 s3 存储桶,您可以将此步骤添加为 Makefile 中的另一个目标。

How to build and deploy on AWS?如何在 AWS 上构建和部署?

make build
make deploy

I have struggled with this as well, and I was using your slice-node-modules successfully for a while.我也为此苦苦挣扎,并且我成功地使用了您的slice-node-modules一段时间。 As I have consolidated more of my projects into monorepos and begun using shared dependencies which reside as siblings rather than being externally published, I ran into shortcomings with that approach.当我将更多的项目合并到 monorepos 中并开始使用作为兄弟而不是外部发布的共享依赖项时,我遇到了这种方法的缺点。

I've created a new tool called lerna-to-lambda which was specifically tailored to my use case.我创建了一个名为lerna-to-lambda的新工具,它是专门为我的用例量身定制的。 I published it publicly with minimal documentation, hopefully enough to help others in similar situations.我用最少的文档公开发布了它,希望足以帮助处于类似情况的其他人。 The gist of it is that you run l2l in your bundling step, after you've installed all of your dependencies, and it copies what is needed into an output directory which is then ready to deploy to Lambda using SAM or whatever.它的要点是,在安装所有依赖项之后,您在捆绑步骤中运行l2l ,并将所需内容复制到 output 目录中,然后准备好使用 SAM 或其他方式部署到 Lambda。

For example, from the README, something like this might be in your Lambda function's package.json :例如,在 README 中,您的 Lambda 函数的package.json中可能包含这样的内容:

"scripts": {
  ...
  "clean": "rimraf build lambda",
  "compile": "tsc -p tsconfig.build.json",
  "package": "l2l -i build -o lambda",
  "build": "yarn run clean && yarn run compile && yarn run package"
},

In this case, the compile step is compiling TypeScript files from a source directory into JavaScript files in the build directory.在这种情况下, compile步骤是将源目录中的 TypeScript 个文件编译到build目录中的 JavaScript 个文件中。 Then the package step bundles up all the code from build along with all of the Lambda's dependencies (except aws-sdk ) into the directory lambda , which is what you'd deploy to AWS.然后package步骤将build中的所有代码与 Lambda 的所有依赖项( aws-sdk除外)捆绑到目录lambda中,这是您要部署到 AWS 的目录。 If someone were using plain JavaScript rather than TypeScript, they could just copy the necessary.js files into the build directory before packaging.如果有人使用纯 JavaScript 而不是 TypeScript,他们可以在打包之前将必要的 .js 文件复制到build目录中。

It's likely that your solution is still working fine for your needs, but I thought I would share this here as an alternative in case others are in a similar situation and have trouble using slice-node-modules.您的解决方案很可能仍能很好地满足您的需求,但我想我会在这里分享这个作为替代方案,以防其他人处于类似情况并且在使用 slice-node-modules 时遇到问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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