Serverless Lambda Functions with Netlify

What is Serverless?

Serverless computing refers to a backend architecture in which you are not responsible for maintaining your own server to run server-side code.

Instead, you write functions, upload them to a Serverless computing service (ex. AWS Lambda), and the service will run the functions when called.

The service you are using (ex. AWS Lambda) takes care of all the infrastructure for you. So “Serverless” does not mean no servers are involved. Instead, it means you don’t have to deal with the headache of taking care of the server(s) yourself.

Netlify Lambda

Netlify Lambda is powered by AWS Lambda, but just much simpler.

We are going to be using Netlify Lambda to build a simple application.

Build a simple application

Note: must have Node.js Version 10 or later

1) Create a new React app

2) Install the Netlify CLI

You have 2 options for installing the CLI:

Option 1: Install it globally

npm install netlify-cli -g

Option 2: Install it as a dev dependency in project

npm install netlify-cli --save-dev

3) Create a functions folder and make a new .js file inside

This is where we store all of our Lambda functions

I will call my file sayHello.js

4) Inside the file, write this basic boilerplate

Each JavaScript file holds one Lambda function.

The function must export a handler method with the following general syntax:

exports.handler = async function(context, event) {
}

Netlify provides the event and context parameters when the Serverless function is called.

When you call the Serverless function endpoint, the handler receives an event object.

The context parameter includes info about the context in which the Serverless function was called.

Because async functions return a Promise, Netlify recommends returning a response with HTTP status code instead of allow function to time out

exports.handler = async function(context, event) {
   return {
        statusCode: 200,
        message: JSON.stringify({msg: "Hello world"})
    }
}

5) Create netlify.toml file at the root level of the directory

This is a configuration file on how Netlify will build and deploy the site.

command: the command that starts the dev server

functions: where we store our Serverless functions

[build]
command = 'npm run build'
functions = 'functions'
publish = 'build'

6) Run the project

In the project directory, run the command netlify dev. This starts a local dev server

If you append /.netlify/functions/sayHello to the URL, the server will send the message defined earlier ({msg: “Hello world”})

The full URL:

localhost:4000/.netlify/functions/sayHello

7) Call function in frontend

This is an example of how you could access the data with axios. You would probably use React Hooks to asynchronously get the data and put it in a view.

const results = await axios.get('/.netlify/functions/sayHello')

As you can see, you use a local URL in the GET request

What is a Dynamic Website?

How is a dynamic page rendered? When the user requests a site, the server queries one or more databases for content, then passes result to templating engine which formats everything into an HTML file for user (dynamically rendered)

With each request from the end user, the HTML code the user gets back from the server is not always the same. The HTML markup you get back adjusts dynamically on the server

Dynamic: things change on the server and new requests can yield a different file
Static: the files never change, they sit on the server and you always get the same exact version

The server returns a dynamically generated HTML page. That page is not necessarily always the same because the HTML code and even the JS code can be generated on the server

The server is not involved in page rendering after serving the HTML/CSS/JS files. Although, page content can still be changed via JS in the browser)

The server side is not doing anything on the loaded page once it’s in the browser. Dynamic rendering is really about that first render when you send the request and get back a page

Dynamic does NOT mean that there’s no HTML page being served— it’s just built dynamically for each request

  • Finished page is served but needs to be generated first
  • Better for SEO because all the page’s content is available on first load
  • Users don’t have to wait for the data after page loads, but they do have to wait for page to load
  • Security tends to be easy to implement because it’s so common for dynamic sites
  • Requires a hosting service which supports the chosen server-side language (and version). Dynamic hosts tend to be more complex to setup and expensive

AWS EC2/ Elastic Beanstalk, Heroku

What is a Static Website?

A static website is a website that only contains only contains HTML, CSS, and/or (client-side) JS files.

Static simply means that the site is not generated on the server. Instead of being rendered dynamically, the HTML, CSS, and JS just sit there waiting on a server for a user to request them. Every user will see the same version of the files.

Static does NOT mean that the page never changes — it’s just pre-built during development. You can still make pages interactive with client-side JavaScript, API calls, etc. Any rendering/changing that is done happens in the browser.

Rendering in the browser means faster changes because you don’t have to wait for information from the server with each update, but the data needs to be fetched after the initial rendering so the initial rendering is slower than a dynamic website/ server-side rendering.

It’s very important these days that things update constantly and that we give immediate feedback. That tends to be easy with static apps because JavaScript runs in the browser, you don’t need to wait for a response from the server to change things. Although, the first page load is slower with static sites than dynamic sites because the data needs to be fetched from the server after the initial render of the static HTML files.

Some advantages of static websites:

  1. Speed/ performance
  2. Version control for content
  3. Security
  4. Less hassle with the server
  5. Traffic surges
  6. Only static host is needed (i.e. it only needs to serve HTML, JS, CSS)
    • Static hosts tend to be cheaper, setup is typically easier (ex. AWS S3, Firebase Hosting)

Some disadvantages of static websites:

  1. No real-time content
  2. No user input
  3. No admin UI
    • As opposed to the incredibly easy publishing processes of sites such as WordPress or Medium, posts on static sites are typically written in Markdown & require the regeneration of the site (watch functionality does this automatically) in order to publish them and deploy the files to a server
  4. You might get performance issues since server might be more powerful than user’s browser
  5. SEO inefficiencies: search engine may not see the client-side rendered data, it only sees what’s initially on the page
  6. JavaScript in the browser can be dangerous security-wise

How Does the Internet Work?

The Internet is really just a giant wire. It connects every computer in the world (with Internet access) to each other. Two computers in entirely different corners of the world can communicate and transfer data back and forth through the Internet.

Some of these computers attached to the Internet have a very special job. They have to be online 24/7 ready to serve you all of the data and the files that you are requesting when you try to access websites. These computers that are doing that job are called servers. A computer that an everyday user uses to access the Internet is called a client.

Internet Service Provider (ISP): the company you pay to get access to the Internet. In the US, for example, this would be companies like Comcast & AT&T

DNS Server: responsible for translating domain names to numeric IP addresses; Domain Name System Server

IP address: postal address for your computer; every single computer connected to the Internet has an IP address

Internet Backbone: underwater cables that connect across the world that power the Internet

  1. Client requests a website (ex. https://google.com)
  2. Browser sends a message to ISP
  3. ISP relays request to a DNS Server
  4. DNS Server looks up website’s IP address in its database (216.58.210.46)
  5. DNS Server finds the IP address & sends it back to browser
  6. Now knowing the exact address, the client makes a direct request to the address through the ISP
  7. Request goes through ISP then through Internet Backbone and ends up at the Server that is located at the IP address
  8. Server sends all of the files back to client through the Internet Backbone and ISP

Type this IP address into your browser (216.58.210.46) and the browser will serve up the Google Home page.

Internet backbone - Wikipedia
The Internet Backbone’s wires literally span across the entire globe, hidden underwater

JWTs (JSON Web Tokens)

What is JWT used for?

It is used for authorization, not authentication. Authentication is checking if a username and password are correct then logging a user in. Authorization is making sure that the user that is sending requests to your server is the same user that actually logged in during the authentication process.

The basic idea of JWT is a simple way for securely transmitting information between parties as a JSON object

What is the JSON Web Token structure?

A JWT is basically just a bunch of random characters. The token is separated into 3 sections: Header, Payload, and Signature. These sections are separated by dots (.) The structure looks like the following:

xxxxx.yyyyy.zzzzz

The JWT website (https://jwt.io) offers a great breakdown of an actual token:

Header

The header typically consists of two parts: the type of the token, which is JWT, and the signing algorithm being used. Here’s an example:

{
   "alg": "SHA256", 
   "typ": "JWT" 
}

Then, this JSON is Base64Url encoded to form the first part of the JWT.

Payload

The payload is the data that you want to send within the token. In the example, the data being sent is a variable called name with a value of John Doe.

{ 
   "sub": "1234567890", 
   "name": "John Doe",
   "admin": true 
}

Another example might be sending an id variable with a unique value that differentiates all of the users of a website.

Signature

To create the signature part you have to take the encoded header, the encoded payload, a secret, the algorithm specified in the header, and sign that.

To create the signature part you have to take the encoded header, the encoded payload, a secret, the algorithm specified in the header, and sign that.

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)

The signature is used to verify the message wasn’t changed along the way, and, in the case of tokens signed with a private key, it can also verify that the sender of the JWT is who it says it is.

The output is three Base64-URL strings separated by dots that can be easily passed in HTML and HTTP environments.

Implementing JWT in Node applications

First, install the jsonwebtoken package with npm.

npm i jsonwebtoken

Get access to JWT in the file

const jwt = require("jsonwebtoken");

Create the payload

const payload = { 
   user: { 
      id: user.id 
   }
}

Sign the token. Pass in the payload, pass in the secret, and inside the callback, we’ll either get the error or a token. If we get a token, we’ll send a response back to the client with that token.

jwt.sign(
   payload, 
   config.get('jwtSecret'), 
   { expiresIn: 360000 }, 
   (err, token) => {
      if (err) throw err;
      res.json({ token });
});

When you create a new user, if everything is successful, the callback should return a token like this:

{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjp7ImlkIjoiNWYwMjY2ZWM3ZjE4Y2JmNTg0NjgwZDM0In0sImlhdCI6MTU5Mzk5Mjk0MCwiZXhwIjoxNTk0MzUyOTQwfQ.8qiRsqHH-mSSrr9itAQzmSLUu8easVTNdeoUxg0AC0U"
}

If we paste this token that we’ve just created into the website that I showed you earlier, we can breakdown it’s header, payload, and signature:

In the payload, you can see our User object with its unique Mongo id (“user”, “id”), the date that the token was issued at (“iat”), and the expiration date that we defined (“exp”).