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
- First API
- Exception handling
- Guards
- Microservices Support
- GraphQL
- Express/Fastify
- More goodies
- Wrapping up
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!"
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.
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.
- Schema first : where the definition is written in GraphQL Schema Definition Language (SDL)
- 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 👍.
Top comments (9)
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.
Interesting post. Looks cool.
Wonderful write-up! Inspirational article for beginners... Cheers :)
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
Well done !