Make your lambda functions lightweight

cemdev

Cesar Muñoz

Posted on August 17, 2021

Make your lambda functions lightweight

I see a lot of articles on how to create a lambda with simple steps, always showing the hello world. But every time you start using dependencies in your lambda function, it starts to weigh.

So, this article will show you how to make your lambda more lightweight and have only the function that we need to execute

Before jumping into the code you need these requirements:

1) AWS CLI installed
2) Configure your aws credentials locally with aws configure.
3) Obviously node installed (We are going to use node v12)
4) Serverless installed npm install -g serverless

Do you have it all configured? Alright! Let's start coding!! 🙂

First, I wanna show you the problem

Create a folder or create a repo and clone it. In my case, I created a repo and clone it.

CreateRepo

I will use npm to install the dependencies, you could use yarn if you want to

> npm init -y
Enter fullscreen mode Exit fullscreen mode

npmInit
This will create a package.json

Now we are going to create our lambda function with

> sls init aws-node-rest-api
Enter fullscreen mode Exit fullscreen mode

slsInit

We are going to make a few changes to the project.

The aws-node-rest-api will change it to src and copy serveless.yml from src in our root folder

> mv aws-node-rest-api src
> mv src/serveless.yml ./serverless.yml
Enter fullscreen mode Exit fullscreen mode

Moving Files

And the last thing to change will be the path of where is our lambda function

Before

app: aws-node-rest-api
service: aws-node-rest-api

provider:
  name: aws
  runtime: nodejs12.x

functions:
  hello:
    handler: handler.hello
    events:
      - http:
          path: /
          method: get
Enter fullscreen mode Exit fullscreen mode

After

app: aws-node-rest-api
service: aws-node-rest-api

provider:
  name: aws
  runtime: nodejs12.x

functions:
  hello:
    **handler: src/handler.hello**
    events:
      - http:
          path: /
          method: get
Enter fullscreen mode Exit fullscreen mode

I highlighted the changed path of the lambda function.

And that's it. Let's deploy our function!!

> serverless deploy
Enter fullscreen mode Exit fullscreen mode

After a while, you'll get the following picture

Deployed

And if you go to aws you can see your new lambda function!! YEY!!! GOOD JOB!!!

AwsFunction

And if go to see what is deployed in our lambda function we can see the code

AwsFunctionCode

Now that we are experts in serverless and lambda functions we want to add some packages

Our lambdas won't we simple right? most of the time we are using packages, to do some calls to the database, call an aws feature, call an api, manipulate an image, etc.

Now, let's install some packages. Let's say we are going to manipulate some images, in our case we are going to use jimp (this is only for the example. I needed a heavy npm package)

So in our console let's type the following command

> npm install --save jimp
Enter fullscreen mode Exit fullscreen mode

And now let's deploy again a see what's going on

> severless deploy
Enter fullscreen mode Exit fullscreen mode

AwsFunctionNoCode

Wait! What? Cannot see the code? What's going on?

Well, with the simple configuration we are uploading the node_modules folder into our lambda function and the package that we just installed makes the lambda too large to show the code.

How can avoid this and see my code again!!? Lambda Layers to the rescue!!

That's right! serverless has the ability to create Lambda Layers. A Lambda Layer is a ZIP archive that contains libraries or other dependencies. With that, we can make our lambda function smaller again.

How we can achieve this? We are going to put our node_modules folder in a Lambda Layer.

For this, we are going to make a few changes to our code.

First, we are going to install this package

> npm i --save-dev serverless-hooks-plugin
Enter fullscreen mode Exit fullscreen mode

and after that, we are creating a deployment folder and create a script where it has all the things that we need to create the layer.

> mkdir deployment
> touch deployment/prepare.sh
Enter fullscreen mode Exit fullscreen mode

In our prepare.sh we are going to copy the following code

echo '****** Starting Pre Deploy Script ******'
echo '1- Creating folder for layers and copy package.json' 
rm -rf ./.dist
rm -rf ./.serverless-layers
mkdir -p .serverless-layers/node-layers/nodejs
cp package.json .serverless-layers/node-layers/nodejs/
echo 'DONE!' 

echo '2 - Change path to serverless-layer, adding LIB dependency, remove npm and yarn files'
cd .serverless-layers/node-layers/nodejs
npm i --production
rm package.json
rm package-lock.json
cd ../../..
echo 'DONE!' 

echo '****** Finished Pre Deploy Script ******'
Enter fullscreen mode Exit fullscreen mode

Basically we are creating a nodejs folder inside .serveless-layes/node-layers, copying the package.json from our root folder and install all the dependencies.

Then, in our package.json we are adding a new script

"deploy:prepare": "sh deployment/prepare.sh"
Enter fullscreen mode Exit fullscreen mode

Leaving our package.json something like this.

{
  "name": "serverless-aws-node-layer-example",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "deploy:prepare": "sh deployment/prepare.sh",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/cesmunoz/serverless-aws-node-layer-example.git"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "bugs": {
    "url": "https://github.com/cesmunoz/serverless-aws-node-layer-example/issues"
  },
  "homepage": "https://github.com/cesmunoz/serverless-aws-node-layer-example#readme",
  "dependencies": {
    "jimp": "^0.16.1"
  },
  "devDependencies": {
    "serverless-hooks-plugin": "^1.1.0"
  }
}
Enter fullscreen mode Exit fullscreen mode

And the last thing, we need to make this steps in our serveless.yml.

Adding the following things:

1) Using the custom hook that the package serverless-hooks-plugin provides us

plugins:
  - serverless-hooks-plugin

custom:
  hooks:
    before:package:createDeploymentArtifacts:
      - npm run deploy:prepare
Enter fullscreen mode Exit fullscreen mode

2) Creating the layer

layers:
  nodeModules:
    path: ./.serverless-layers/node-layers
    name: My-App-Node-Dependencies
    description: Node Modules for My App
    compatibleRuntimes:
      - nodejs12.x
    package:
      include:
        - ./**
Enter fullscreen mode Exit fullscreen mode

3) Make our function package individually and exclude everything

package:
  individually: true
  exclude:
    - ./**
Enter fullscreen mode Exit fullscreen mode

4) Include only our handler.js in the lambda function and make use of the lambda layer

functions:
  hello:
    handler: src/handler.hello
    layers:
      - { Ref: NodeModulesLambdaLayer }
    package:
      include:
        - src/handler.js        
    events:
      - http:
          path: /
          method: get
Enter fullscreen mode Exit fullscreen mode

The final serveless.yml will be something like this:

app: aws-node-rest-api
service: aws-node-rest-api

provider:
  name: aws
  runtime: nodejs12.x

plugins:
  - serverless-hooks-plugin

custom:
  hooks:
    before:package:createDeploymentArtifacts:
      - npm run deploy:prepare

layers:
  nodeModules:
    path: ./.serverless-layers/node-layers
    name: My-App-Node-Dependencies
    description: Node Modules for My App
    compatibleRuntimes:
      - nodejs12.x
    package:
      include:
        - ./**

package:
  individually: true
  exclude:
    - ./**

functions:
  hello:
    handler: src/handler.hello
    layers:
      - { Ref: NodeModulesLambdaLayer }
    package:
      include:
        - src/handler.js        
    events:
      - http:
          path: /
          method: get
Enter fullscreen mode Exit fullscreen mode

Let's deploy it again and see what happens

> serverless deploy
Enter fullscreen mode Exit fullscreen mode

AwsFunctionCodeAgain

Woala! We can see our code again!

And Where is our lambda layer?

AwsLambdaLayer

We can see and the lambda function has a dependency on our new lambda layer

And if we go to lambda layers we can see it's there

AwsLayers

So with that configuration we can view always our code.

Hope you found it useful as I do.

Repo: https://github.com/cesmunoz/serverless-aws-node-layer-example

See you next time!!

C.

💖 💪 🙅 🚩
cemdev
Cesar Muñoz

Posted on August 17, 2021

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related