Go Serverless with NodeJS and AWS Lambda
Make your NodeJS Express API run serverless and deploy it to AWS
Serverless architecture is an alternative to high-maintenance, resource-wasting servers. With serverless deployments, you only have to pay for precisely what you use. And it frees you from having to handle multiple server setups and their configurations.
So, it’s no surprise that developers today flock to go serverless with their applications. With the help of AWS Lambda and Serverless framework, you can quickly deploy applications that scale.
In this tutorial, we are looking at deploying a simple serverless API with Node.js, AWS Lambda, and the Serverless framework.
A bit about these technologies
AWS Lambda is a cloud-based serverless service. Lambda functions are stateless functions that are triggered by events and expired at the end of their execution.
Given the complex nature of AWS Lambda, we use the Serverless framework to simplify the deployment process. In fact, with Serverless, you can deploy your Node application in just a few steps.
Prerequisites
To continue with this tutorial, you need to have the following things set up.
- An AWS account . If you are only experimenting with AWS, you can join a free tier without having to pay a dime.
- Create an IAM user in your AWS console. Follow the steps in this post to create the IAM user. Remember to save the access key Id and secret access key before going to the next step.
Install and setup Serverless
You can install Serverless easily with npm. Run the following command to install it globally.
npm install -g serverless
Next, configure installed Serverless with IAM keys using the following command. Use the ID and key saved when creating the IAM user as key and secret, respectively.
sls config credentials --provider aws --key xxx --secret xxx
Create the Node application
I created a simple Hello World application for this tutorial, but you can deploy more complex applications following the same logic.
const express = require("express");
const sls = require("serverless-http");
const app = express();
app.get("/", (req, res) => {
res.send("Hello World");
});
app.get("/:userName", (req, res) => {
res.send(`Welcome, ${req.params.userName}`);
})
module.exports.handler = sls(app);
As you can see above, we use the serverless-http
npm package to setup the serverless application, so make sure you have the package installed. You can install the library with:
npm install --save express serverless-http
Create the serverless.yml file
We use a file named serverless.yml to pass Serverless configurations. For our simple application, it contains the following properties.
service: node-serverless-app
provider:
name: aws
runtime: nodejs10.x
stage: dev
region: eu-central-1
functions:
app:
handler: app.handler
events:
- http:
path: /
method: ANY
- http:
path: /{proxy+}
method: ANY
Here, the functions
property lists all the functions in our application. We pass a single function named app
and uses the exported reference to the handler in the app.js
file as the function handler.
Then, we need to add the events that would trigger the given function. We pass the HTTP requests as the triggering events. I have set it up in the above configuration to call the app function every time an HTTP request is sent.
The use of /{proxy+}
forwards every request allowing the Express application to handle every request by itself instead of handling the requests at the API gateway level.
Deploy the application
Now that we have passed our configuration to the serverless.yml
deploying the application is only a single command matter.
sls deploy
And its output will look like this.
Congratulations! You have successfully deployed your first serverless application to AWS.
You can visit the deployed application at the links provided under endpoints. If you visit the root, you will see the message “Hello World”.
Path specific routing
Remember how we proxied all the routes to the Express application? Though there are benefits to this implementation, like limiting cold starts, we miss out on benefitting from some serverless architecture features.
Instead of routing all the paths with one Lambda function, we can introduce path specific routes that are handled by different Lambda functions. It allows us to get a better insight into the application using path-specific metrics.
In that case, update the serverless.yml
like this so that a different function handles each path.
functions:
helloWorld:
handler: app.handler
events:
-http:
path: /
method: get
welcome:
handler: app.handler
events:
-http:
path: /{userName}
method: get
Adding environment variables
If you want to pass environment variables to the application, you can use the environment
property.
For example, if you want to pass a NODE_ENV variable, you can set it up like this.
provider:
name: aws
runtime: nodejs10.x
stage: dev
region: eu-central-1
environment:
NODE_ENV: production
If you want to pass the environment variables from a .env file, you need to use the serverless-dotenv-plugin
.
First, install the plugin as a development dependency.
npm install serverless-dotenv-plugin --save-dev
You can then create a .env file in the root directory and add the environment variables to it.
STAGE=dev
SECRET=**********
Once you have listed the dotenv-plugin under application plugins, you can import the stored environment variables and use them inside the serverless.yml file.
service: node-serverless-app
provider:
name: aws
runtime: nodejs10.x
stage: ${env:STAGE}
region: eu-central-1
environment:
SECRET: ${env:SECRET}
functions:
helloWorld:
handler: app.handler
events:
- http:
path: /
method: get
welcome:
handler: app.handler
events:
- http:
path: /{userName}
method: get
plugins:
- serverless-dotenv-plugin
Use Serverless Offline
Until this point, we had to deploy our application even to carry out the simplest of route tests. You only have to write two-three new routes in your application to realize how annoying this is.
What if there is a way to test your application before deploying it to AWS?
With the use of the serverless-offline plugin, you can do just that. You only have to install a new npm package and add one new line of code to the serverless.yml file to make this work.
First, install the package.
npm install serverless-offline --save-dev
Then, update serverless.yml.
plugins:
- serverless-offline
- serverless-dotenv-plugin
Now, you simply have to run the following command to start the application locally.
sls offline start
It will show you a list of all the routes in your application. Also, most importantly, it starts your application running locally on port 3000.
You can now test the application routes by visiting them on your browser with the URL, http://localhost:3000.
Summary
Serverless architecture is still in its early days compared to servers. You can count on it becoming even more powerful and prominent in the coming years. I hope your first experience with Serverless and AWS Lambda tempted you to give this technology a chance next time you are looking for a deployment option.
Thanks for reading!
Source: livecodestream