visit
is sponsoring this blogpost for the next month. I tried it out the other day. It's like serverless but for running entire back ends. You can host and scale apps automagically. Pretty neat.
I’ve dabbled a fair share in the dark arts of Serverless. Digging into the various pros and cons of not having dedicated servers, or instances you can call your own. Even if they technically are not. They’re just in some undisclosed server farm somewhere floating in the cloud.
Many of the use cases make sense to let the cloud provider handle the server management, scaling and up time. You’re a developer, why should you need to get your hands dirty with the horror of the command line. Ew, the terminal! How do you exit Vim again? *shivers*
Learning new things is not easy, believe me. I’m not in any way an above average developer. Learning is hard, even if you’re a dev, and used to learning new things. Shifting your mindset to using Serverless Architecture is not a small feat. Here’s my take on starting slow. I’ll show you how to use the code you’re already used to, and apply it to a Serverless environment.If you have an app in production, you can cut costs drastically. With the auto-scaling properties of using Serverless Architecture you can rest assured it will always serve all the users hitting your API. So, if you ever make it big and get featured on Tech Crunch, the influx of users won’t break all your servers, and leave your users hanging. Pun intended.The goal will be to take an existing Express API and edit it slightly to be deployed to AWS through the Serverless framework. I’ll expect you already have an AWS account and an installation of the Serverless framework set up and working on your machine. If not, please check this out and follow along the steps to set up an installation of the Serverless framework. Otherwise, if you more prefer screen casts, a course where I explained it through video.
I’ve taken the liberty of creating a small repo with an Express REST API. It’s from one of my previous articles you may have read. My point for taking an existing Express API is to show how easy it is to migrate it to using Serverless.
First let’s clone the repo to our machine. We’re grabbing the
dev
branch where I’ve set up all the necessary modules and configurations.$ git clone -b dev //github.com/adnanrahic/nodejs-restful-api.git
This will clone the repo into a directory named
nodejs-restful-api
. Open it up in a code editor of choice. We have some work to do.First thing’s first. Installing node modules.$ npm install
Running
npm install
will install all modules from the package.json file. That shouldn’t take longer than a few seconds.Once that’s done we need to configure the database connection. We keep this in the db.js file. Opening it up you see mongoose is connecting to a database connection URL which we keep in an environment variable.
// db.js
var mongoose = require('mongoose');
mongoose.connect(process.env.DB, { useMongoClient: true });
We set this environment variable in an .env file. A sample file is present named sample.variables.env. Let’s open it up and rename it to variables.env.
// variables.env
DB=mongodb://localhost:27017/test
Note: If you want to follow along coding in this tutorial please create a MongoDB Atlas database cluster. This will be used once we deploy the application to AWS. You can follow along the tutorial here to learn how to create an Atlas cluster or this tutorial to create an mLab instance.
What’s left to do is just run the server. Jump back to the terminal.$ node server.js
Don’t forget to pick “Form URL Encoded” as the content type. Change the method to GET and remove the request body. Now check if the user was added correctly.
Guess what, you can use the code above and deploy it to AWS using the Serverless framework with just a couple of minor changes. Actually, you’re just replacing a couple of lines in the server.js file, and installing one more module. Lastly, you add a Serverless configuration file named serverless.yml. That’s it!
// server.js
// before
require('dotenv').config({ path: './variables.env' });
var app = require('./app');
var port = process.env.PORT || 3000;
var server = app.listen(port, function() {
console.log('Express server listening on port ' + port);
});
// after
require('dotenv').config({ path: './variables.env' });
var app = require('./app');
var serverless = require('serverless-http');
module.exports.handler = serverless(app);
We’re replacing the server with the module. This module is then given the whole Express app object and exported with a handler. We’ll configure this handler in the serverless.yml file. But first install the module.
$ npm install --save serverless-http
There we go. Create the new serverless.yml file in the root of the project directory, and paste this code in. It’s very important to keep the indents correct, hence why I’ve added it as a gist.
service: express-app
provider:
name: aws
runtime: nodejs6.10
stage: dev
region: us-east-1
memorySize: 128
functions:
app:
handler: server.handler
events:
- http:
path: /
method: ANY
cors: true
- http:
path: /{proxy+}
method: ANY
cors: true
plugins:
- serverless-offline
What’s happening here is that you’re hooking the handler function from the server.js file to the / endpoint. On AWS it will mean the whole app object will be created as a single Lambda function with one main API Gateway route. How cool is this!?
You may have noticed the plugins section in the serverless.yml file. It states one plugin named
serverless-offline
. We need this to run a local emulation of Lambda and API Gateway.$ npm install --save-dev serverless-offline
$ sls offline start --skipCacheInvalidation
$ sls deploy
Hope you guys and girls enjoyed reading this as much as I enjoyed writing it.
Do you think this tutorial will be of help to someone? Do not hesitate to share. If you liked it, smash the clap below so other people will see this here on Medium.