NestJS :  a backend nodeJS framework for the enterprise
Tags: node, frameworks, nestjs
Published: 2020-01-09 08:47:04

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` :smiley:.

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 <a href="https://nestjs.com" target="_blank">NestJS</a>. 

>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](https://expressjs.com/) or [fastify](https://www.fastify.io/).

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](#installation)
 * [First API](#first-api)
 * [Exception handling](#exception-handling)
 * [Guards](#guards)
 * [Microservices Support](#microservices-support)
 * [GraphQL](#graphql)
 * [Express/Fastify](express-fastify-)
 * [More goodies](#more-goodies)
 * [Wrapping up](#wrapping-up)

# Installation

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

```bash
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.

```bash
cd my-first-project
npm run start
```

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

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/pn0c9koasnkvjxje20ox.png)

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

```shell
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

```shell
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](https://thepracticaldev.s3.amazonaws.com/i/h92prpoiodafpjerdd9f.png)

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

```typescript
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](http://localhost:3000/time) using postman / browser / curl

You will now see the below response as json.
```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 = <base url> + @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.

```typescript
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. 

```typescript
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

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

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

```typescript
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.

```bash
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](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.

```bash
npm i --save @nestjs/platform-fastify
``` 

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

```typescript
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](https://docs.nestjs.com/recipes/swagger), [Jest](https://docs.nestjs.com/fundamentals/testing), [Supertest](https://docs.nestjs.com/fundamentals/testing), [TypeORM](https://docs.nestjs.com/recipes/sql-typeorm), [Sequelize](https://docs.nestjs.com/recipes/sql-sequelize), [Terminus](https://docs.nestjs.com/recipes/terminus), [Compodoc](https://docs.nestjs.com/recipes/documentation), [Custom decorators](https://docs.nestjs.com/custom-decorators) and lots more...

# Wrapping up

IMHO [NestJS](https://nestjs.com) 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 :+1:.