TUTORIAL

Building and Distributing NodeJS 12.x Express Serverless Application With Lyrid

Handoyo Sutanto
8 minutes
December 20, 2020
Handoyo Sutanto
8 minutes
December 20, 2020

Introduction

This is a series of tutorials that will start building mainly focusing on showcasing how things work and how to build an application using Lyrid. This example specifically will show you how to deliver a standard NodeJS 12.x running Express Web Server as a Lyrid application.

Although these blogs are about our own technology, you will soon see that there is nothing in this platform that requires you to conform with a non-standard method of building an application. Everything you do here can still carry forward to writing an application on your own Virtual Machine. For instance, Docker Container, or Kubernetes.

Prerequisites

Initial Setup

First you will need to register your Lyrid account:

Register Here To Start Lyrid

And go through the 3 sections:

This whole guide assumes that you already registered with Lyrid, downloaded our command line client, and initialized the client with your access and secret key.

You will then need to clone the base project. For this example, it is hosted at GitHub:

git clone https://github.com/LyridInc/lyrid-expressjs.git

Local Build and Test

To run the sample locally, simply run these commands:

cd lyrid-expressjs
npm install
npm start

Simple…so far so good…let's dig into what we have in the code. This sample REST API is quite simple:

It contains a basic index.js where it will initialize an express web server application instance, and the function entry point (entry.js) will define how this instance is built along the routes. There’s a logging middleware (morgan: http://expressjs.com/en/resources/middleware/morgan.html) that logs every request for this application.

This service has two routes:

/echo/* : This endpoint will just echo all your request url, and method then prints it out as a text response. Test it with Insomnia by passing HTTP POST Method and /echo/hello_world request:

Looks good!

/sharp/ : We will get into this endpoint in the later portion of the tutorial.

Lyrid Definition File and Entry Point

Let’s explain a bit about this GitHub project example. The structure of the code is similar to our initial code when you run:

lc code init --name "$AppName" --module "$ModuleName" --function "$FunctionName" --language "nodejs12.x" --web "express"

Except in this case we already prefilled all those names and description.

A few things to explain in this template is the .lyrid-definition.yml file, and inside it there is an entry point called entry.js

Changing this definition file is not required, but it is crucial to explain how this file is being used by our platform.

The definition file contains descriptors that will be used in our platform to identify how the function will be built and packed. In this scenario, because it is an Express Project, our build will expect an express server instance application to be returned from the entry point (entry.js). The user has the flexibility to modify the entry point to include more routes and middleware inside the project, and our platform will take in the express server instance and wrap the instance for different types of serverless platforms.

The definition file determines how your function will be called inside our API Gateway.

NOTES: This is specific for our NodeJS 12.x Support. Our current support for NodeJS and Express is only for non-asynchronous function execution, and continues until the event loop is empty or the function times out. We will have support for asynchronous Promise based type of wrapper soon.

Public Cloud Deployment

Now your code is working locally, the next question is: how to make this API run on a publicly accessible endpoint?

Run our submission command from the folder that contains our definition file:

lc code submit

In this stage, your function will be zipped, and wrapped by our platform and the platform will perform a build to create a build artifact for all the public cloud serverless platforms that we support.

At the end of the submission, save the endpoint generated by the platform.

In this stage, we went through a standard serverless function build. This runs the pre-built installation using npm install and packages the function as an application.

Run the following command to monitor your build output:

lc monitor -c '*.build.*'

When your build is deployed to your default execution platform, your function is published and ready to use.

Public Cloud Execution

Now that your application is deployed, execute it using our endpoint. Remember the structure of our endpoint is currently:

This turns your endpoint to (if you didn’t change any names in the lyrid definition): https://api.lyrid.io/x/node/express/latest/entry/

When testing with HTTP client like Insomnia, remember to change the authorization to Basic on this tab and fill in your Lyrid access key as username and Lyrid secret key as the password:

Let’s execute this by clicking on the Send button:

Looks good! The app is now hosted inside our platform.

Similarly, you can also test out calling the application using cURL command like this (on Mac or Linux):

curl -u $LYRID_ACCESS:$LYRID_SECRET https://api.lyrid.io/x/node/express/latest/entry/echo/hello_world

Where $LYRID_ACCESS and $LYRID_SECRET corresponds to your access key and secret key.

You can monitor your LYR execution logs using our lc monitor function and filter for all LYR execution in your account:

lc monitor -c '*.execute.LYR'

Express Sharp Endpoint

The other endpoint that we have in this example is our implementation of an image processing that uses a high performance Node.js image processing called Sharp: https://sharp.pixelplumbing.com/

We take inspiration from this GitHub page: https://github.com/pmb0/express-sharp/tree/3.1.1

And made little modifications to the endpoint to be able to support any URL given to the function. The URL format is as follows:

/resize/:width/:height?format=$format&progressive=true&quality=90&crop=false&gravity=center&url=$image_url

Where:

  • width: integer, the fixed width of the output image.
  • height (optional): integer, the fixed height of the output image. If not provided, it will maintain the aspect ratio of the image.
  • format (optional): string enum, valid values are one of the format supported by sharp: https://sharp.pixelplumbing.com/api-output#toformat. Default: webp if supported else, the output format of the requested image.
  • progressive (optional): boolean, only for jpeg and png. Use &progressive=true to enable progressive scan.
  • quality (optional): integer (1–100). quality is a Number between 1 and 100. Default if 80.
  • crop (optional): boolean. Use &crop=true to enable the sharp cropping feature. Default is false. Note: Both width and height params are neccessary for crop to work.
  • gravity(optional): string enum. When the crop option is activated you can specify the gravity of the cropping. Possible attributes of the optional gravity are north, northeast, east, southeast, south, southwest, west, northwest, center and center. Default is center;
  • url: string. URL to original image.

Let's test this function locally and look for a publicly accessible image URL at Imgur. I will use this one: https://i.imgur.com/3a0qwRe.jpeg

The original image has resolution of 701x701 pixel and 56KB in size.

Let's run though this image with a few different parameters locally first with base URL of http://localhost:3000/sharp and HTTP method of GET in your Insomnia Client:

GET /resize/250/150?crop=true&gravity=north&url=https://i.imgur.com/3a0qwRe.jpeg
Resize to 250x150 and crop with gravity=north
GET /resize/500?format=webp&quality=25&url=https://i.imgur.com/3a0qwRe.jpeg

Scale the image with fixed height of 500, converts it to WEBP format and quality=25

The cropped and resized imaged above is much less than the original image (4.9KB and 6.3KB). Change the endpoint with base URL to http://api.lyrid.io/x/node/express/latest/entry/sharp and add your Access Key and Secret just like the previous section, and test it again. You just hosted an image processing service that you can use to dynamically resize, crop and convert any publicly accessible image.

Sharp is a very complex image processing library, and unfortunately we will not dive further into the what it can/cannot do. We just want to show you in this blog that we are able to integrate complex libraries and package them into a simple API using Lyrid.

Conclusion

In this tutorial, we want to show a basic use-case of our platform. Hopefully, this has given something that can be easily followed and to show how our platform works. More of these upcoming tutorial series will touch on examples that:

  • Connects to a Database
  • Connects to a Storage
  • More Middlewares: CORS, JWT Authentication, etc2.
  • Seamlessly moves your application to another public cloud (AWS or GCP) while maintaining the same endpoint.

Notice in this whole process, apart from our command line client, you did not even touch or download any library, framework, or tool to make this work on a different cloud provider. This follows our philosophy of “Only Focus on Your Code — BUT It Still Should Be Able to Run Anywhere”. We are abstracting anything that is not related to your code (the build, distribution and execution).

Along with NodeJS 12.x + ExpressJS, the same flow can be done with our support for:

  • Django + Python 3.8
  • Flask + Python 3.8
  • Gin + Golang 1.x
  • ASP.NET + .NET Core 3.1
  • And more upcoming support

And with that, you can register a Free Lyrid account to get started with this following link and try these all yourself:

Register Here To Start Lyrid

Lastly, please do not be shy to contact me at hsutanto@lyrid.io or join our Slack channel to say hi and let us know if there are any issues for you following this example.

Thank you for reading and stay safe!

Handoyo

Schedule a demo

Let's discuss your project

Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

99 South Almaden Blvd. Suite 600
San Jose, CA
95113

Jl. Pluit Indah 168B-G, Pluit Penjaringan,
Jakarta Utara, DKI Jakarta
14450

copilot