loading...

NestJS : a backend nodeJS framework for the enterprise

vinodsr profile image Vinod S R ・6 min read

Last week an idea stuck my mind to explore the frameworks available in nodeJS ecosystem to develop backend API, which is scalable and efficient. I was using expressJS long time for my projects. It's time to think about the alternate future 😃.

I started listing down all the features that would be required for a good nodeJS backend framework (purely based on my understanding).

  • Modularity
  • Easy to develop
  • Integration with other applications
  • Extensibility
  • Maintainable
  • Performance
  • Easy to test and deploy
  • DevOps support ready
  • Support for microservices
  • REST & GraphQL

I took my special analyser googles, fuelled up my Time Machine and started my journey to future in search for my query. Went through frameworks like express, Koa, hapi, molecular, Seneca etc. But none had full-filled my need, until i saw NestJS.

Nest (NestJS) is a futuristic framework for building efficient, scalable Node.js server-side applications. It uses progressive JavaScript, is built with and fully supports TypeScript (yet still enables developers to code in pure JavaScript) and combines elements of OOP (Object Oriented Programming), FP (Functional Programming), and FRP (Functional Reactive Programming). It is build on top of typescript (javascript version is also available). The framework is built by taking the concepts of Angular putting it on top of expressJS or fastify.

Yes you heard it right. I can change the underlying core framework to either express or fastify without changing any API code. Fastify has got proven track record when it comes to performance.

Let's have a look in to how you can setup the nestJS framework.

Chapters ahead

Installation

The installation is pretty much straight forward. You can use npm/yarn to install the framework.

npm i -g @nestjs/cli
nest new my-first-project

The cli will ask for the type of package system you want (npm/yarn).
Once the installation is complete you can start the application using the start script.

cd my-first-project
npm run start

Open any browser and try http://localhost:3000. You will now see the "Hello World!"

Alt Text

Hurray!

You can also use npm run start to start in the application in dev mode. This will watch for any changes in the code and restart the application.

First API

In most of the nodeJS backend framework, for writing a API, we will create a callback method for the defined URL. This is not followed in nestJS.

If you have a Angular/Spring boot background, you will find the below features very similar to Angular/Spring boot

In nestJS, in order to create an API we need a controller which is similar to a component in Angular (or a RestController in Springboot).

Let's say i need to create a time api which returns the current server time.

Run the following cli command inside your project directory to create a new controller

nest g controller time

Where time is our controller name

This will create two files. The time.controller.spec.ts is the test file and time.controller.ts is our main file

CREATE /src/time/time.controller.spec.ts (479 bytes)
CREATE /src/time/time.controller.ts (97 bytes)
UPDATE /src/app.module.ts (322 bytes)

You can see that it updates the app.module.ts file to add the reference to the new controller time.controller. This is similar to bootstrapping a component in Angular.

This is how the folder structure looks after you create a controller.

Alt Text

Open the time.controller.ts and replace the code with the below code

import { Controller, Get } from '@nestjs/common';

@Controller('time')
export class TimeController {
    @Get()
    getTime(): any {
      return {
          time : new Date(),
      };
    }
}

Restart the application (If you had started in dev mode, it will restart automatically) and access http://localhost:3000/time using postman / browser / curl

You will now see the below response as json.

{
  "time": "2019-12-31T05:06:31.805Z"
}

If you gave an argument in the @Get decorator then the API url will change accordingly.

So the effective url of an API = + @Controller's url + @Get's url

Similar to @Get, NestJs also supports other REST verb like @post , @Put, @Update, @Delete etc..

What ever object is returned from the method is sent back to the client as the result of the API.

You can get more details about the controller implementation @ https://docs.nestjs.com/controllers

This is one of the simplest API implementation in nodeJS, similar to Java's Spring boot implementation.

Exception handling

In nodeJS we use try/catch or exception middleware to handle the errors in the application.

But in NestJS, the approach is unique.

You can create a filter class that can handle the specific exceptions.

import { ExceptionFilter, Catch, ArgumentsHost, HttpException } from '@nestjs/common';
import { Request, Response } from 'express';

@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
  catch(exception: HttpException, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse<Response>();
    const request = ctx.getRequest<Request>();
    const status = exception.getStatus();

    response
      .status(status)
      .json({
        statusCode: status,
        timestamp: new Date().toISOString(),
        path: request.url,
      });
  }
}

This means if an HttpException is thrown from any part of the application, this filter is triggered, the logic executes and a response is sent back to the client.

Easy ? uh ?

More details @ https://docs.nestjs.com/exception-filters

Guards

Security is very critical. Typically in a expressJS application we use middleware to check for the auth level of an API.

In nestJS we can use guards for this purpose.

import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
import { Observable } from 'rxjs';

@Injectable()
export class RolesGuard implements CanActivate {
  canActivate(
    context: ExecutionContext,
  ): boolean | Promise<boolean> | Observable<boolean> {
    return true;
  }
}

and in the controller

@Controller('cats')
@UseGuards(RolesGuard)
export class CatsController {}

You can also create global guards in app.module.ts

const app = await NestFactory.create(AppModule);
app.useGlobalGuards(new RolesGuard());

Microservices Support

One of the biggest advantage of this framework is it's out of the box support for microservices and transport layers. It has got the support for different transport layers like TCP, gRPC, MQTT, RabbitMQ etc...

You can read more about microservices @ https://docs.nestjs.com/microservices/basics

GraphQL

NestJS has got out of the box support for GraphQL. It starts with installing the GraphQL support package.

npm i --save @nestjs/graphql apollo-server-express graphql-tools graphql

NestJS offers two methods of integrating GraphQL.

  1. Schema first : where the definition is written in GraphQL Schema Definition Language (SDL)
  2. Code first: where we use decorators to generate the GraphQL schema

You can read more about GraphQL integration @ https://docs.nestjs.com/graphql/quick-start

Express / Fastify ?

Another impressive feature of NestJS is that, it can run on top of express or fastify frameworks. You don't have to change you API's code for that. If you want to access any native framework features of epxress / fastify, it is possible.

By default NestJS uses express framework. If you want to use fastify framework, then you can install the package for fastify.

npm i --save @nestjs/platform-fastify

Once installed you need to modify the module.ts with the below code

import { NestFactory } from '@nestjs/core';
import {
  FastifyAdapter,
  NestFastifyApplication,
} from '@nestjs/platform-fastify';
import { ApplicationModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create<NestFastifyApplication>(
    ApplicationModule,
    new FastifyAdapter()
  );
  await app.listen(3000);
}
bootstrap();

Now your application is ready for fastify.

Benchmark results shows that fastify has got more performance than express

More goodies

Further more it has got out of the box support for Swagger, Jest, Supertest, TypeORM, Sequelize, Terminus, Compodoc, Custom decorators and lots more...

Wrapping up

IMHO NestJS is a framework which can be used in small backend applications to large enterprise level application. It helps you in building an efficient, scalable application. The maintainability of this framework is huge compared to other nodeJS framework. I had seen projects using expressJS where the code maintainability has become a serious concern after some months of development. The ability to switch express and fastify is one of the cool features of NestJS.

Head on to https://nestjs.com to start developing your app.

Happy Coding 👍.

Posted on by:

vinodsr profile

Vinod S R

@vinodsr

programmer, photographer, human

Discussion

markdown guide
 

We are using NestJS on production and it is really cool!

 
 

Awesome, Nice write-up 👍👏

 

Awesome! Hearing NestJS for the first time...

 

Awesome, nestjs is really cool.

 

Awesome! Can be migrated from the existing Express project to Nest?

 

It is possible . But you may have to invest in some time and effort. Not that easy migration. But once you migrate the maintenance is very easy compared to vanila nodejs and express

 

Wonderful write-up! Inspirational article for beginners... Cheers :)