NestJS a JavaScript framework that can be used to build scalable and dynamic server side applications very quickly and easily, NestJS is built with TypesScript and supports TypeScript out of the box, it feels very much like using Angular but on the backend, you see the project was heavily influenced by Angular. NestJS enforces a certain application structure and this is one of the benefits of using NestJS.
NestJS combines the best of OOP and functional programming, it also exploits the benefits of using TypeScript. It is built upon some popular libraries that we use to build NodeJS server side applications like Express and Cors. NestJS is a high level abstraction that is built on these simple libraries, so much thought has been put into the framework development and some of the obvious benefit that comes from using the framework includes;
- Reduction of unnecesary code
- Fast development time
- Ease with testing apps
No matter how cool we say JavaScript really is, there are some pitfalls that comes with using JavaScript, especially for server side apps. There is often the problem of file and module structure, lack of types, there's often too much duplicated code, and it is quite difficult to test your app, all these are problems familiar to some developers and the goal of using NestJS is to provide an elegant solution to all these problems.
Nest JS was built to give projects a certain level of structure, most often junior developers struggle with choosing the right project structure, handling application dependencies and other third party plugins. NestJS is the right tool for the junior developer, or anyone who has trouble adopting a particular application structure. It is also a good solution to the afore mentioned problems. NestJS also makes it incredibly easy for us to test our applications.
Installation
To install NestJS you have to ensure that you have NodeJS installed on your PC, then you can run;
npm i -g @nestjs/cli
This installs the very capable NestJS CLI that comes baked in with some commands that can allows us to spin up new projects and lots of other utility features we will need when building applications with NestJS.
We can scaffold a new nestjs project by running
nest new project-name
This will scaffold a project for us with some basic code, you can now proceed to opening up the project in your favorite text editor. The two commands we just ran are;
npm i -g @nestjs/cli
nest new project_name
Alternatively you can clone the starter template git
git clone https://github.com/nestjs/typescript-starter.git project_name;
Navigate into the newly created folder, and install the dependencies.
cd project_name;
npm install;
Folder Structure
A NestJS project will often posses the following folder structure depending on which version you are using, as of the time of this writing, NestJS is in version 9.0.5
. We will only concern ourselves with the src
folder, that's going to be the only folder we will be working with most of the time. That's where our application source code will be stored.
src/----------|------app.controller.ts
|------app.service.ts
|------app.module.ts
|------main.ts
main.ts
This file contains the file necessary code for bootstrapping and starting our application. It imports NestFactory
and the main module for our application, creates a server app for us and listens on a specified port for an incoming request.
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
await app.listen(3000, () => console.log(`App started on PORT 3000`));
}
bootstrap();
Calling the create()
method of NestFactory
builds a http application for us from the application main module, The app that is returned by this method satisfies the NestExpressApplication
interface and this interface exposes some useful methods for us. We start the http server by calling app.listen()
as we would have with an express app. If it isn't apparent, you now see the benefit of working with NestJS, enabling CORS
on our application is as simple as calling app.enableCors()
on our application. Ordinarily it would require us to first install cors
module and then using it as a middleware. To create our http app/server we need to pass in our applications main module as an argument to the create
method of NestFactory
, we would look at the app.module.ts
below.
app.module.ts
A module in NestJS is simply a data structure for managing our applications dependencies. Modules are used by Nest to organize the application structure into scopes. Controllers and Providers are scoped by the module they are declared in. Modules and their classes (Controllers and Providers) form a graph that determines how Nest performs, for a class to serve as a NestJS module it should be decorated with the @Module()
decorator. Let's examine the contents of the app.module.ts
.
import { Module } from '@nestjs/common';
import { AppController } from './app.controller.ts';
import { AppService } from './app.service.ts';
@Module({
imports: [],
controllers: [AppController],
providers: [AppService]
})
export class AppModule {}
The imports array is responsible for handling other modules that this module depends on, as our application grows we would have other modules because NestJS suggests that each feature in application should have it's own module, rather than polluting the global module namespace. The imports array handles those other modules. The controllers
array handles the contorllers that we create in our application, while the providers array handles services
that we create in our application. The module class also scopes the controllers and providers, making them available only in the module they are registered with. We are going to have a brief overview of contorllers
and services
.
app.service.ts
A service in NestJS is similar in concept to a service in Angular, a service is just a class that encapsulates helper methods in our application, we define functions that helps get certain things done, in this example we define only one method on app.service.ts
which returns hello world! Another name for a service is a provider. Let's inspect our app.service.ts
file.
import { Injectable } from '@nestjs/common';
@Injectable()
export class AppService {
getHello(): string {
return 'Hello World!';
}
}
For a class to serve provider it should be decorated with the @Injectable
which is exported by @nestjs/common
, we can proceed to declaring methods on the class that we use in our code.
app.controller.ts
A controller is a just another fancy name for a route handler, a controller will define a method that is usually attached to a route, whenever there is a request to the server that matches a particular route, the controller will call the function that is attached to the route.
import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';
@Controller()
export class AppController {
constructor(private readonly appService: AppService) {}
@Get()
getHello(): string {
return this.appService.getHello();
}
}
We already established that NestJs makes use of dependency injection, in the above controller we inject the AppService
provider so we can use the methods declared on it. For a class to serve as a controller it should be decorated with the @Controller
decorator as demonstrated above, the decorator can accept a string as an argument, that string will serve as a base route for that controller. Http verbs can be applied as decorators to the functions that will process an incoming request. In the above example, a @Get
decorator which matches to the http verb GET
is applied to the getHello
function. Thus whenever there is a GET
request to the server, the getHello
function is called as the handler to that route.
The decorators that serve as http verbs also accepts strings as argument and they serve as a secondary path to match after the one defined in the @Controller
. In the above example, the base route is /
because no argument is passed into the @Contorller
decorator and the route for the @Get
controller is also /
because no argument is also passed to the @Get
decorator attached to the getHello
function that is why a request made to the server http://localhost:3000/
will return hello world
.
Starting the app
To kick start the server, we simply run;
npm start
The NestJS CLI which you have access to if installed with npm i @nestjs/cli
will bootstrap and start the application for us in production mode. To start the server in development mode, which enables hot reload we can run npm i start:dev
and any changes we make while the server is running locally will take effect.
In fututre articles in this series we will take our time to explore NestJS providers, controllers, modules and lots of other features of NestJS, that is it for today, i hope you enjoyed this and i hope you found this useful, please leave your comment down below about what your thoughts or experience on using NestJS, feel free to add in anything you feel i left out in this introduction in the comments.