amplify-backend
amplify-backend copied to clipboard
Amplify Gen 2 Lambda Functions: additional files / modules / lambda layers
Environment information
System:
OS: macOS 14.4.1
CPU: (12) arm64 Apple M2 Pro
Memory: 217.09 MB / 32.00 GB
Shell: /bin/zsh
Binaries:
Node: 20.9.0 - ~/.nvm/versions/node/v20.9.0/bin/node
Yarn: undefined - undefined
npm: 10.1.0 - ~/.nvm/versions/node/v20.9.0/bin/npm
pnpm: undefined - undefined
NPM Packages:
@aws-amplify/backend: 0.13.0-beta.14
@aws-amplify/backend-cli: 0.12.0-beta.16
aws-amplify: 6.0.25
aws-cdk: 2.134.0
aws-cdk-lib: 2.134.0
typescript: 5.4.3
AWS environment variables:
AWS_STS_REGIONAL_ENDPOINTS = regional
AWS_NODEJS_CONNECTION_REUSE_ENABLED = 1
AWS_SDK_LOAD_CONFIG = 1
No CDK environment variables%
Description
In Amplify Gen 2 can we have a way to include additional files including node modules within a lambda function, either using lambda layers and/or an alternate approach
Hi @domthomas1, dependencies that are imported by your lambda handler code are automatically bundled with your function code. We currently don't have a mechanism to include other assets in the bundled artifact but you could use CDK overrides to create and attach a lambda layer to your function.
Amplify CDK Override docs: https://docs.amplify.aws/gen2/build-a-backend/add-aws-services/overriding-resources/ CDK LayerVersion docs: https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda.LayerVersion.html#class-layerversion-construct CDK function .addLayer docs: https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda.Function.html#addwbrlayerslayers
Hi @edwardfoyle thanks for your response.
I was able to get some module dependencies included in the lambda as you suggested, although I had to use different approaches depending on the module.
For example, const { Sha256 } = require('@aws-crypto/sha256-js'); worked ok, while the openai module didn't using that approach, and i needed to resort to referencing a copy of the module using import OpenAI from '../openai/nodejs/node_modules/openai/index.mjs';.
It's not clear to me if I should add lambda dependencies to the root package.json under dependencies or devDependencies as this is a back-end component which isn't required in the front-end. Or if I should use another approach if the module isn't found automatically.
The other thing to note is that the dependencies get added to the lambda index.mjs file adding thousands of lines to the original code making traversing the code more difficult. So lambda layers would be a more preferable approach to me. I'll have a deeper dive into the links provided to see if i can work out how to implement layers into Amplify Gen 2, although I'd appreciate any example code that you might be able to provide to help expedite this if possible?
It's not clear to me if I should add lambda dependencies to the root package.json under dependencies or devDependencies
lambda dependencies can be added as devDependencies because they are only required during build time to bundle the lambda code
should use another approach if the module isn't found automatically
The function code is bundled using esbuild and it should be able to find any module in the node_modules of the project. If you have repro steps for a specific issue here, we can take a look at what's going on.
adding thousands of lines to the original code making traversing the code more difficult
Can you explain your use case for looking at the bundled output? Are you trying to debug a specific issue?
any example code that you might be able to provide
Setting up the lambda layer should look something like the following in your amplify/backend.ts file:
import { myFunc } from './path/to/function/resource';
import { Stack } from 'aws-cdk-lib';
import * as lambda from 'aws-cdk-lib/aws-lambda';
const backend = defineBackend({
myFunc,
});
const lambdaFunction = backend.myFunc.resources.lambda as lambda.Function;
const layerVersion = new lambda.LayerVersion(Stack.of(lambdaFunction), 'customLayer', {
code: lambda.Code.fromAsset('./path/to/layer/directory'),
})
lambdaFunction.addLayers(layerVersion);
hi @edwardfoyle thanks for your response. However I've been unable to add the openai module as a lambda layer having tried numerous layer paths.
This includes ../node_modules/openai, ./functions/openai, subdirectories and files, and ./functions/openai/nodejs/node_modules/openai/index.mjs. This latter path was the only one I was able to get working when importing the openai module from within the function handler directly, so not using a layer (using import OpenAI from '../openai/nodejs/node_modules/openai/index.mjs';)
code:
import { defineBackend } from '@aws-amplify/backend';
import { auth } from './auth/resource';
import { data } from './data/resource';
import { myDemoFunction } from './functions/my-demo-function/resource';
import { promptHandler } from './functions/prompt-handler/resource';
import { requestHandler } from './functions/request-handler/resource';
import { Stack } from 'aws-cdk-lib';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import { storage } from './storage/resource';
const backend = defineBackend({
auth,
data,
myDemoFunction,
promptHandler,
requestHandler,
storage,
});
const lambdaFunction = backend.requestHandler.resources.lambda as lambda.Function;
const layerVersion = new lambda.LayerVersion(Stack.of(lambdaFunction), 'customLayer', {
code: lambda.Code.fromAsset('./functions/openai'),
})
lambdaFunction.addLayers(layerVersion);
I get the error:
Caused By: Error: Cannot find asset at /Users/dominic/code/amplify/react-amplify-gen2/functions/openai
at new AssetStaging (/Users/dominic/code/amplify/react-amplify-gen2/node_modules/aws-cdk-lib/core/lib/asset-staging.js:1:2119)
Resolution: Check your backend definition in the `amplify` folder for syntax and type errors.```
@edwardfoyle Thank you so much for working on amplify and helping us with these questions. I can build a layer, but it seems to be larger than I would like to track in github. So I'm thinking of building the layer by hand and then using the amplify stack to just pull down the zip file when creating the layer or just pull down a prebuilt-custom layer. But I'm not sure how to import an existing layer into my CDK stack (written in typescript.)
Would it be too much to give me some direction on how I might incorporate a prebuilt-custom layer in the CDK in amplify when adding a stack to the backend?
Thanks!
Hey folks, we have a RFC open to enable support for this: https://github.com/aws-amplify/amplify-backend/issues/1549. We would love to hear your feedback on this. Closing this issue.