Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I use shared code in lambdas in an AWS SAM template using layers in Node.js?

We have a very simple use case--we want to share code with all of our lambdas and we don't want to use webpack.

We can't put relative paths in our package.json files in the lambda folders because when you do sam build twice, it DELETES the shared code and I have no idea why.

Answer requirements:

  • Be able to debug locally
  • Be able to run unit tests on business logic (without having to be ran in an AWS sandbox)
  • Be able to run tests in sam local start-api
  • Be able to debug the code in the container via sam local invoke
  • sam build works
  • sam deploy works
  • Runs in AWS Lambda in the cloud
like image 700
Brandon Avatar asked Dec 22 '22 19:12

Brandon


1 Answers

TL;DR

  • Put your shared code in a layer
  • When referencing shared code in the lambda layer, use a ternary operator when you require(). Check an environment variable that is only set when running in the AWS environment. In this case, we added a short AWS variable in the SAM template, but you can find environment variables that AWS automatically defines, but they will not be as short. This enables you to debug locally outside of the AWS stack, allowing very fast unit tests that test business logic.
let math = require(process.env.AWS ? '/opt/nodejs/common' : '../../layers/layer1/nodejs/common');
let tuc = require(process.env.AWS ? 'temp-units-conv' : '../../layers/layer1/nodejs/node_modules/temp-units-conv');
  • You shouldn't need to use the ternary operator like that unless within the lambda folder code

Here's a working example that we thought we'd post so that others will have a much easier time of it than we did. It is our opinion that AWS should make this much easier.

https://github.com/blmille1/aws-sam-layers-template.git


Gotchas

The following gotcha has been avoided in this solution. I am mentioning it because it looked like a straight-forward solution and it took a lot of time before I finally abandoned it.

It is very tempting to add a folder reference in the lambda function's package.json.

//...
"dependencies": {
    "common":"file:../../layers/layer1/nodejs/common"
},
//...

If you do that, it will work the first sam build. However, the second time you run sam build, your shared code folder and all subdirectories will be DELETED. This is because when sam builds, it creates an .aws-sam folder. If that folder exists, it performs an npm cleanup, and I think that is what provokes the deleting of the shared code.

like image 168
Brandon Avatar answered May 12 '23 11:05

Brandon