NestJs – A backend NodeJS framework

NestJs – A backend NodeJS framework

Introduction

Nest (NestJS) is a 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

  1. OOP (Object Oriented Programming),
  2. FP (Functional Programming), and
  3. FRP (Functional Reactive Programming).

Why choose NestJS among many other powerful NodeJS frameworks out there? As of July 2020, it boasts over 28k GitHub stars. The improvement of JavaScript as a web development programming language has been the reason behind the rise of many JavaScript frameworks. And NestJS is not an exception. With so many cool features, NestJS can help the developers to easily and efficiently create backend applications, RESTful API.

*** A survey on stateofjs.com on most used Javascript frameworks 2019 shows that Nest is also one of the most popular Javascript frameworks besides Express, Next.js, Koa, Meteor, Sails, Feathers, Nuxt, Gatsby.

Credit: stateofjs.com

 

Installation and create new NestJS application

Please make sure that Node.js (>= 10.13.0) is installed on your operating system

Setting up a new project is quite simple with the Nest CLI. With npm installed, you can create a new Nest project with the following commands in your OS terminal:

$ npm i -g @nestjs/cli

Install nestjs-cli

$ nest new project-name

Create new project

The project directory will be created, node modules and a few other boilerplate files will be installed.

Next, run the program by typing the following command:

npm start

Then go to the browser at http://localhost:3000, we should see the app is running.

Configure and switch between ExpressJS and Fastify

There are two HTTP platforms that NestJS can support: Express and Fastify.

Express:  is very popular among Nodejs web development community. Express is a well-known minimalist web framework for node.

Fastify: has better performance. It is a high performance and low overhead framework highly focused on providing maximum efficiency and speed.

You can choose the one that best suits your needs.

By default, Nest makes use of the Express framework.

import './LoadEnv';
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { ValidationPipe } from '@nestjs/common';
async function bootstrap() {
  try {
    const app = await NestFactory.create(AppModule);
    app.useGlobalPipes(new ValidationPipe());
    await app.listen(process.env.PORT || 3000);
  } catch (err) {
    console.log(err);
  }
}
bootstrap();

To configure NestJS to use Fastify, firstly we need to install the required package:

$ npm i --save @nestjs/platform-fastify

Inside bootstrap function in main.ts, import the package and configure to use Fastify as the following code:

const app = await NestFactory.create<NestFastifyApplication>(
  AppModule,
  new FastifyAdapter()
);

Routing in NestJS

Routing in NestJS is very easy to be defined. We’ll use the @Controller(‘users’) decorator to define the base routing for users. The routes for Post, Get, Put, Delete, Param, and Body marked by Nestjs annotation.

GET /users

GET /users/id

POST /users

Using a path prefix in a @Controller(‘users’) decorator allows us to easily group a set of related routes, and minimize repetitive code.

@Controller('users')
export class UsersController {
  @Get()
  find() {
    return this.usersService.find();
  }
  @Get(':id')
  findById(@Param('id') id) {
    return this.usersService.findById(id);
  }
  @Post()
  add(@Body() createUserDto: CreateUserDto) {
    return this.usersService.add(createUserDto);
  }
  @Patch(':id')
  update(@Param('id') id, @Body() updateUserDto: UpdateUserDto) {
    return this.usersService.update(id, updateUserDto);
  }
}

We can access the request object by instructing Nest to inject it by adding the @Body() decorator to the handler’s signature.

@Post()
 add(@Body() createUserDto: CreateUserDto) {
   return this.usersService.add(createUserDto);
}

@Param() is used to decorate a method parameter. As seen in the code below, we can access the id parameter by referencing @Param(‘id’).

@Get(':id')
  findById(@Param('id') id) {
    return this.usersService.findById(id);
}

Main concepts in Nest

Providers: are a fundamental concept in Nest. Many of the basic Nest classes may be treated as a provider – services, repositories, factories, helpers, and so on. The main idea of a provider is that it can inject dependencies; this means objects can create various relationships with each other, and the function of “wiring up” instances of objects can largely be delegated to the Nest runtime system. A provider is simply a class annotated with an @Injectable() decorator.

Let’s start creating simple service. UsersService – This service is responsible for storing and returning data, and is designed for use by UsersController, so we should create a provider so that these two classes can create relationships with each other.

@Injectable()
export class UsersService {
  constructor(
    @InjectRepository(User)
    private usersRepository: Repository<User>,
  ) {}
  async findOne(username: string): Promise<User | undefined> {
    return this.usersRepository.findOne({ name: username });
  }
  async find(option?: FindManyOptions<User>): Promise<User[]> {
    return this.usersRepository.find(option);
  }
  async findById(id: number): Promise<User> {
    return this.usersRepository.findOne(id);
  }
  async add(user: CreateUserDto): Promise<User> {
    return this.usersRepository.save(user);
  }
  async update(user: UpdateUserDto): Promise<User> {
    return this.usersRepository.save(user);
  }
}

HINT: It is possible to create a service using CLI: nest g service users @Injectable () will help Nest know that this is a provider. So Nest will automatically create an instance of this class and pass it to the UsersController:

 

Modules: A module is a class annotated with a @Module() decorator. The @Module() decorator provides metadata that Nest makes use of to organize the application structure.

Each application has at least one module, a root module.  Each module can stand for a specific component or feature in your application. Modules are strongly recommended as an effective way to organize your components. Your source code structure may look like this:

GraphQL in Nest

As many know, GraphQL is a powerful query language for APIs and a runtime for fulfilling those queries with your existing data. With NestJS, we can also a powerful GraphQL server.

Assuming that you already have a basic understanding of GraphQL, now let’s jump to find out how to use GraphQL with Nest.

Start by installing the required packages:

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

Depending on what underlying platform you use (Express or Fastify), you must also install either apollo-server-express or apollo-server-fastify.

Here is a list of the key concepts you need to know about:

  1. Schema
  2. Query
  3. Mutation
  4. Type
  5. Resolver

Nestjs provides us with two different ways of building GraphQL applications:

  1. Schema first
  2. Code first

Summary

With all the features that have been listed above, it verifies that NestJS has so many cool features that can help the developers to easily build a server-side application. Even though it still has some drawbacks but its power and usefulness can not be denied. Below is the summary of pros and cons of Nest:

 

Pros:

Open source

Powerful but super friendly to work with

Easy to understand documentation

Fast development

Angular style syntax for the backend

NodeJS ecosystem

Graphql support easy

Good architecture

Typescript makes it well integrated in vscode

 

Cons:

User base is small. Less help on Stackoverflow

Updates with breaking changes

Unstable

Difficult to debug

References

https://expressjs.com/

https://www.fastify.io/

https://docs.nestjs.com/graphql/quick-start

https://docs.nestjs.com/techniques/performance

https://docs.nestjs.com/fundamentals/execution-context#reflection-and-metadata

https://medium.com/google-developers/exploring-es7-decorators-76ecb65fb841

https://www.apollographql.com/blog/graphql-vs-rest-5d425123e34b/