DEV Community

Nikhil Gautam
Nikhil Gautam

Posted on

Introduction to Serverless Functions

Most of you might have heard (maybe...) the buzzword "Serverless", this might sound some server-side magic which hosts your code without a server (which is totally wrong). In reality, this is a very easy and fast way to get a piece of code up and running on a remote server.

Anyhow, in this article, I will be de-mystifying the serverless architecture and sharing with you everything I know about this topic.

What are Serverless Functions?

Well, let's talk about servers first.

Normally, when we ship our code to a server for hosting a website ( as an example ), we as a user of the server are solely responsible for scaling the app, the security of the app, restarting if it crashing or fixing bugs on the production like a boss. And that can take a lot of time sometimes, and it's even more frustrating when the size of the application is small or is only be supposed to be used a microservice. Also, the over-payment if you don't that level of computing power.

So, what serverless proposes is that, hey, we'll take care of scaling, performance and most of the deployment stuff, you just need to provide us a function with does the task you want to do and follow a few rules. And you just pay only for what you use.

And, AWS calls those functions Lambda functions, GCP... Google Cloud Functions, Azure... Azure Functions.. and on and on.... if there exist good cloud tech, every provider will jump on it like a kangaroo. These platforms are called Functions-as-a-Service (FaaS).

In this article, we will be using Netlify Functions it's not as big of a company as Amazon or Google, but it's more powerful as it is very easy to use compared to the alternative, also a bonus integrates very well with other Netlify products (btw which are awesome and you should check them out).

Netlify Functions in the background uses AWS Lambda functions so you can use almost the same things that you learn here and implement on AWS.

When should you use Serverless Functions?

In use, Lambda Functions ( in javascript ) are very similar to some like NodeJS, you can do to simple calculations, API calls, use is-odd npm package ( yup that exists ), etc - general NodeJS stuff.

Every serverless function lives in a separate Javascript file, this file name will also be later used in the routing.

Also, dependencies and shared code are also allowed.

That means, if you are a front-end developer then you don't need to worry about maintaining a separated Node Application. If you are a back-end developer, then you can hand-off a few ( not very frequently used ) task to separate serverless functions, like login and logout, and adopt a kind-off microservice design.

Serverless functions are a ready-to-go function, especially with Netlify's CI/CD features. Even with alternatives like PaaS solutions like Heroku which allow very easy deployment setup, this process is still much easier to maintain and use as Functions live inside your main project without the need of maintaining a separate project. Even with Docker containers, you still have to manage them.

For front-end devs, serverless functions can be a huge time saver.

Lets Begin...

Prerequisite Node Packages

In this article, we will be using the following NodeJS packages.

  • netlify:- This is the official Netlify CLI. We can use init, deploy and set up your functions, so we will be installing this globally.
  $ npm install -g netlify
  • netlify-lambda:- This is an amazing tool which allows us to test the functions in a local dev environment ( with auto-reload ) and also compile them to netlify functions.
  $ yarn add netlify-lambda
  • axios:- Axios is a promise-based HTTP client for the browser and node.js. We will be using it have some fun later on.
  $ yarn add axios

Also, I will be using Yarn in this tutorial.

Folder Structure

We will be using the following folder structure in this article:-

.
├── function
│   └── getTest.js
|   └── getMichaelScott.js
├── netlify.toml
├── package.json
└── yarn.lock

So, lets breakdown this structure -

  • function:- In this folder, we will be storing all the functions we will we be writing.
    • getTest.js:- This an example function, all the functions will be, similarly, stored in separate files. We will be exploring the contents of this file in later sections.
    • getMichaelScott.js:- Well... I like The Office, not my fault. (Its a file containing a function, duh)
  • netlify.toml:- This is the config file for Netlify, here pass can pass deployment and build configurations.
  • package.json:- NodeJS package configuration file.
  • yarn.lock:- Auto-generated file by Yarn for package indexing.

Project Setup and Config

Scripts

Since we are using the netlify-lambda package for building and dev.

We can add the following scripts in our package.json.

"scripts": {
  "lambda-serve": "netlify-lambda serve function",
  "lambda-build": "netlify-lambda build function"
},

Actually, command syntax is netlify-lambda serve/build <Function Folder>. Since all our functions will live in function folder, our function folder will just function.

Netlify Setup

By default, netlify-lambda puts the functions in lambda folder after building. So, we need to tell Netlify where to find our functions.

So, in the netlify.toml file, we can add:-

[build]
  functions = "lambda"

Now, Netlify will look into the lambda folder, which gets generated when we build the functions, by running

yarn run lambda: build

Onto the Functions

Now, the real deal, the functions. I will show you a basic example first then we will break everything down and understand how this stuff works.

Basic Format

exports.handler = (event, context, callback) => {
  // some legendary code goes here
};

So, every function should return a handler function. This function gets executed when the function's route is hit.
When the function is executed, Netlify passes a 2 parameters i.e. event and context to our function and you must provide a callback function.

  • event:- When your function is hit, Netlify passes an event object which contains data related to the request. It consists of:-
  {
    "path": "Path parameter",
    "httpMethod": "Incoming request's method name",
    "headers": {Incoming request headers},
    "queryStringParameters": {query string parameters},
    "body": "A JSON string of the request payload.",
    "isBase64Encoded": "A boolean flag to indicate if the applicable request payload is Base64-encode"
  }
  • context :- This object provides methods and properties that provide information about the invocation, function, and execution environment. There's a lot of info in this object, too much for me to explain in this article. So, you can check out this link for more info.
  • callback:- Now, this is responsible to send a response. in there you can specify general response stuff, like response body, status code, headers, etc.
  // Parameters
  callback(Error, Response)

  //Possible fields for Response in the Callback function
  {
    "isBase64Encoded": true|false,
    "statusCode": httpStatusCode,
    "headers": { "headerName": "headerValue", ... },
    "body": "..."
  }

  // Working example
  callback(null, {
    statusCode: 200,
    body: "Hello",
  });

  //For Errors
  callback(Error(e))

Lambda can also use async functions, there instead of callback we return response object and throw errors. Read about it more here

Some more Functions

I have put together 2 examples of serverless functions, you can go through these examples, if there are any doubts/confusions/problem you find in these feel free to flood the comments.

Function 1:-

function/getTest.js

exports.handler = (event, context, callback) => {
  callback(null, {
    statusCode: 200,
    body: JSON.stringify({ name: "🚀 serverless is 🔥" }),
  });
};
Function 2:-

function/getRonSwanson.js

import axios from "axios";

export const handler = async (event, context) => {
  const michaelSaid = await axios.get(
    "https://michael-scott-quotes.herokuapp.com/quote"
  );

  if (michaelSaid.status === 200) {
    return {
      statusCode: michaelSaid.status,
      body: JSON.stringify({ michaelSaid: michaelSaid.data.quote }),
    };
  } else throw new Error("Michael left Dunder Mifflin!!");
};

Everbody Dance Now

YAAS 😎.

In Example 2, I have switched up a few things. I have used ES6 syntax, as netlify-lambda package comes with the magical ability to compile it down. Also, I am using Async Function here, so, I can just return an object with same property specified above and throw Errors like a boss.

Runnin' dem functions

To start a local development server, just do:-

$ yarn run lambda: serve

This should start a local dev server w/ auto-reload. By default, it uses port 9000, so to test the functions we visit http://localhost:9000/.

So, you opened that and got an error.

Well...

netlify-lambda maps all functions to a specific route according to the fileName of the Function.

For Example:-

function/getTest.js -> http://localhost:9000/getTest
function/getMichaelScott.js -> http://localhost:9000/getMichealScott

During deployment, there will a few changes here, we'll take a look on that later on.

For now, let's check if everything is fine or not.

Response for function 1:-

➜ curl http://localhost:9000/getTest/
{"name":"🚀 serverless is 🔥"}

Response for function 2:-

➜ curl http://localhost:9000/getMichaelScott
{"michaelSaid":"NO! GOD! NO GOD PLEASE NO! NO! NOOOOOOOOOOOOOOOOOOOOOOOOOOOOO"}

yup, this article is Blessed...

NO! GOD! NO!

Let's Deploy the damn thing

Everything seems fine here at Local Development Land. Let's deploy the damn this.

First of all, we need to put this repo on Github.

FEW INTENSE GIT PUSHS LATER

on Github:- https://github.com/nik-gautam/serverless-article

Onto Netlify

  1. First, go to our profile and click the button "New Site From Git"

New site from Git

  1. Then, choose Github or wherever your repo is present.

Choose Github

  1. Then, choose your Repo.

Choose Repo

  1. Add the required build command, which in our case is yarn run lambda-build. Here, we also need to choose deploy branch which in out the case in the master branch. Any other required deployment config is done here.

Add Build Command

  1. AND DONE!!! Our functions are UP...

Remember, I said there would a change is routing, well, here it is.. to access the functions on the deployed server you would need to hit to following routes.

function/getTest.js -> http://localhost:9000/getTest -> https://{netlify-url}/.netlify/functions/getTest

function/getMichaelScott.js -> http://localhost:9000/getMichealScott -> https://{netlify-url}/.netlify/functions/getMichaelScott

Check out https://nifty-hopper-119d2a.netlify.app/.netlify/functions/getMichaelScott

You can also checkout Function Logs at Functions tab in Site Properties at Netlify.

Conclusion

Congrats!!

Well, that was certainly something.

Serverless is a really useful tech which I think more people should know and use.

This was my first ever Tech Article and I hope to write more soon.

Remember this is not the end of Serverless

Next articles ( if I ever write them ) will be more focused on the practical application of this concept and I will show you how to take this from sheets to the streets.

AND AS ALWAYS one more Michael Scott GIF

Wink Wink

(and Forgive my bad jokes)

Github Repo

Top comments (0)