DEV Community

Nadim Chowdhury
Nadim Chowdhury

Posted on • Edited on

How to learn Nest JS?

Learning NestJS can be a rewarding experience as it is a powerful framework for building efficient and scalable server-side applications. Here's a structured guide to help you get started with NestJS:

Step 1: Understand the Basics of Node.js and TypeScript

Before diving into NestJS, make sure you have a solid understanding of Node.js and TypeScript.

  1. Node.js Basics:

    • Understand the event-driven architecture.
    • Learn how to create a basic server using Node.js and Express.js.
    • Familiarize yourself with asynchronous programming using callbacks, promises, and async/await.
  2. TypeScript Basics:

    • Learn the basic syntax and features of TypeScript.
    • Understand interfaces, classes, and modules.
    • Learn about decorators and their usage.

Step 2: Set Up Your Development Environment

  1. Install Node.js:
    Download and install Node.js from nodejs.org.

  2. Install Nest CLI:
    The Nest CLI is a powerful tool to initialize, develop, and maintain NestJS applications.

   npm install -g @nestjs/cli
Enter fullscreen mode Exit fullscreen mode

Step 3: Create a New NestJS Project

  1. Create a New Project:
   nest new my-nestjs-app
   cd my-nestjs-app
Enter fullscreen mode Exit fullscreen mode
  1. Run the Application:
   npm run start
Enter fullscreen mode Exit fullscreen mode

This will start the development server and your application will be running on http://localhost:3000.

Step 4: Understand the Project Structure

When you create a new NestJS project, you'll see the following structure:

my-nestjs-app/
├── src/
│   ├── app.controller.spec.ts
│   ├── app.controller.ts
│   ├── app.module.ts
│   ├── app.service.ts
│   ├── main.ts
├── test/
├── node_modules/
├── .eslintrc.js
├── .prettierrc
├── nest-cli.json
├── package.json
├── README.md
├── tsconfig.build.json
└── tsconfig.json
Enter fullscreen mode Exit fullscreen mode

Step 5: Learn the Basics of NestJS

  1. Modules:

    • Modules are the building blocks of a NestJS application. They help in organizing the application structure.
    • Example: app.module.ts
     import { Module } from '@nestjs/common';
     import { AppController } from './app.controller';
     import { AppService } from './app.service';
    
     @Module({
       imports: [],
       controllers: [AppController],
       providers: [AppService],
     })
     export class AppModule {}
    
  2. Controllers:

    • Controllers handle incoming requests and return responses to the client.
    • Example: app.controller.ts
     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();
       }
     }
    
  3. Services:

    • Services are used to handle business logic.
    • Example: app.service.ts
     import { Injectable } from '@nestjs/common';
    
     @Injectable()
     export class AppService {
       getHello(): string {
         return 'Hello World!';
       }
     }
    

Step 6: Create a Simple Application

Let's create a simple CRUD application to manage users.

  1. Generate a New Module:
   nest generate module users
Enter fullscreen mode Exit fullscreen mode
  1. Generate a Controller:
   nest generate controller users
Enter fullscreen mode Exit fullscreen mode
  1. Generate a Service:
   nest generate service users
Enter fullscreen mode Exit fullscreen mode
  1. Update Users Service: Open src/users/users.service.ts and implement basic CRUD operations.
   import { Injectable } from '@nestjs/common';

   interface User {
     id: number;
     name: string;
     age: number;
   }

   @Injectable()
   export class UsersService {
     private users: User[] = [];

     findAll(): User[] {
       return this.users;
     }

     findOne(id: number): User {
       return this.users.find(user => user.id === id);
     }

     create(user: User): void {
       this.users.push(user);
     }

     update(id: number, updatedUser: User): void {
       const userIndex = this.users.findIndex(user => user.id === id);
       if (userIndex > -1) {
         this.users[userIndex] = updatedUser;
       }
     }

     delete(id: number): void {
       this.users = this.users.filter(user => user.id !== id);
     }
   }
Enter fullscreen mode Exit fullscreen mode
  1. Update Users Controller: Open src/users/users.controller.ts and implement the endpoints.
   import { Controller, Get, Post, Body, Param, Put, Delete } from '@nestjs/common';
   import { UsersService } from './users.service';

   @Controller('users')
   export class UsersController {
     constructor(private readonly usersService: UsersService) {}

     @Get()
     findAll() {
       return this.usersService.findAll();
     }

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

     @Post()
     create(@Body() user: { id: number; name: string; age: number }) {
       this.usersService.create(user);
     }

     @Put(':id')
     update(@Param('id') id: number, @Body() user: { id: number; name: string; age: number }) {
       this.usersService.update(id, user);
     }

     @Delete(':id')
     remove(@Param('id') id: number) {
       this.usersService.delete(id);
     }
   }
Enter fullscreen mode Exit fullscreen mode
  1. Update Users Module: Open src/users/users.module.ts and import the service and controller.
   import { Module } from '@nestjs/common';
   import { UsersService } from './users.service';
   import { UsersController } from './users.controller';

   @Module({
     controllers: [UsersController],
     providers: [UsersService],
   })
   export class UsersModule {}
Enter fullscreen mode Exit fullscreen mode
  1. Integrate Users Module in App Module: Open src/app.module.ts and import the UsersModule.
   import { Module } from '@nestjs/common';
   import { AppController } from './app.controller';
   import { AppService } from './app.service';
   import { UsersModule } from './users/users.module';

   @Module({
     imports: [UsersModule],
     controllers: [AppController],
     providers: [AppService],
   })
   export class AppModule {}
Enter fullscreen mode Exit fullscreen mode
  1. Run the Application:
   npm run start
Enter fullscreen mode Exit fullscreen mode
  1. Test the Application: Use a tool like Postman or curl to test the CRUD endpoints.

Step 7: Learn More Advanced NestJS Features

  1. Middleware:

    • Middleware functions are executed before the route handler.
    • Example:
     import { Injectable, NestMiddleware } from '@nestjs/common';
     import { Request, Response, NextFunction } from 'express';
    
     @Injectable()
     export class LoggerMiddleware implements NestMiddleware {
       use(req: Request, res: Response, next: NextFunction) {
         console.log(`Request...`);
         next();
       }
     }
    
  2. Interceptors:

    • Interceptors are used to transform the response or handle exceptions.
    • Example:
     import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
     import { Observable } from 'rxjs';
     import { map } from 'rxjs/operators';
    
     @Injectable()
     export class TransformInterceptor implements NestInterceptor {
       intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
         return next.handle().pipe(map(data => ({ data })));
       }
     }
    
  3. Guards:

    • Guards are used for authentication and authorization.
    • Example:
     import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
     import { Observable } from 'rxjs';
    
     @Injectable()
     export class AuthGuard implements CanActivate {
       canActivate(
         context: ExecutionContext,
       ): boolean | Promise<boolean> | Observable<boolean> {
         const request = context.switchToHttp().getRequest();
         return validateRequest(request);
       }
     }
    
  4. Pipes:

    • Pipes are used to transform and validate data.
    • Example:
     import { PipeTransform, Injectable, ArgumentMetadata, BadRequestException } from '@nestjs/common';
    
     @Injectable()
     export class ParseIntPipe implements PipeTransform<string, number> {
       transform(value: string, metadata: ArgumentMetadata): number {
         const val = parseInt(value, 10);
         if (isNaN(val)) {
           throw new BadRequestException('Validation failed');
         }
         return val;
       }
     }
    

Step 8: Testing and Debugging

  1. Unit Testing:

    • NestJS uses Jest for unit testing.
    • Example:
     import { Test, TestingModule } from '@nestjs/testing';
     import
    

{ UsersService } from './users.service';

 describe('UsersService', () => {
   let service: UsersService;

   beforeEach(async () => {
     const module: TestingModule = await Test.createTestingModule({
       providers: [UsersService],
     }).compile();

     service = module.get<UsersService>(UsersService);
   });

   it('should be defined', () => {
     expect(service).toBeDefined();
   });
 });
 ```
Enter fullscreen mode Exit fullscreen mode
  1. End-to-End Testing:

    • Use Supertest for end-to-end testing.
    • Example:
     import { Test, TestingModule } from '@nestjs/testing';
     import { INestApplication } from '@nestjs/common';
     import * as request from 'supertest';
     import { AppModule } from './../src/app.module';
    
     describe('AppController (e2e)', () => {
       let app: INestApplication;
    
       beforeEach(async () => {
         const moduleFixture: TestingModule = await Test.createTestingModule({
           imports: [AppModule],
         }).compile();
    
         app = moduleFixture.createNestApplication();
         await app.init();
       });
    
       it('/ (GET)', () => {
         return request(app.getHttpServer())
           .get('/')
           .expect(200)
           .expect('Hello World!');
       });
     });
    

Step 9: Learning Resources

  1. Official Documentation:

  2. Online Courses:

  3. Books:

    • "Mastering NestJS" by Kamil Myśliwiec
  4. Tutorials and Articles:

  5. Community and Forums:

Step 10: Build Real-World Projects

  1. Choose Real-World Projects:

    • Build applications like an e-commerce platform, blog, or social media app.
  2. Contribute to Open Source:

    • Contribute to open source NestJS projects on GitHub.

Step 11: Stay Updated

  1. Follow NestJS Updates:
    • Follow the NestJS blog
    • Join NestJS newsletters
    • Attend NestJS conferences and meetups

By following this structured guide and practicing regularly, you'll build up your knowledge and skills in NestJS, enabling you to create powerful and efficient server-side applications. If you have any specific questions or need further details on any step, feel free to ask!

Sure! Let's dive into NestJS, a powerful, efficient, and scalable server-side Node.js framework built with TypeScript. Here's a step-by-step guide to help you get started with NestJS:

Step 1: Set Up the Development Environment

  1. Install Node.js:
    Download and install Node.js from nodejs.org.

  2. Install Nest CLI:
    The Nest CLI is a powerful tool to initialize, develop, and maintain NestJS applications.

   npm install -g @nestjs/cli
Enter fullscreen mode Exit fullscreen mode

Step 2: Create a New NestJS Project

  1. Create a New Project:
   nest new my-nestjs-app
   cd my-nestjs-app
Enter fullscreen mode Exit fullscreen mode
  1. Run the Application:
   npm run start
Enter fullscreen mode Exit fullscreen mode

This will start the development server and your application will be running on http://localhost:3000.

Step 3: Understand the Project Structure

When you create a new NestJS project, you'll see the following structure:

my-nestjs-app/
├── src/
│   ├── app.controller.spec.ts
│   ├── app.controller.ts
│   ├── app.module.ts
│   ├── app.service.ts
│   ├── main.ts
├── test/
├── node_modules/
├── .eslintrc.js
├── .prettierrc
├── nest-cli.json
├── package.json
├── README.md
├── tsconfig.build.json
└── tsconfig.json
Enter fullscreen mode Exit fullscreen mode

Step 4: Learn the Basics of NestJS

  1. Main Entry Point:
    • src/main.ts is the entry point of the application.
   import { NestFactory } from '@nestjs/core';
   import { AppModule } from './app.module';

   async function bootstrap() {
     const app = await NestFactory.create(AppModule);
     await app.listen(3000);
   }
   bootstrap();
Enter fullscreen mode Exit fullscreen mode
  1. Modules:

    • Modules are the building blocks of a NestJS application.
    • src/app.module.ts:
     import { Module } from '@nestjs/common';
     import { AppController } from './app.controller';
     import { AppService } from './app.service';
    
     @Module({
       imports: [],
       controllers: [AppController],
       providers: [AppService],
     })
     export class AppModule {}
    
  2. Controllers:

    • Controllers handle incoming requests and return responses to the client.
    • src/app.controller.ts:
     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();
       }
     }
    
  3. Services:

    • Services are used to handle business logic.
    • src/app.service.ts:
     import { Injectable } from '@nestjs/common';
    
     @Injectable()
     export class AppService {
       getHello(): string {
         return 'Hello World!';
       }
     }
    

Step 5: Create a Simple Application

Let's create a simple CRUD application to manage users.

  1. Generate a New Module:
   nest generate module users
Enter fullscreen mode Exit fullscreen mode
  1. Generate a Controller:
   nest generate controller users
Enter fullscreen mode Exit fullscreen mode
  1. Generate a Service:
   nest generate service users
Enter fullscreen mode Exit fullscreen mode
  1. Update Users Service: Open src/users/users.service.ts and implement basic CRUD operations.
   import { Injectable } from '@nestjs/common';

   interface User {
     id: number;
     name: string;
     age: number;
   }

   @Injectable()
   export class UsersService {
     private users: User[] = [];

     findAll(): User[] {
       return this.users;
     }

     findOne(id: number): User {
       return this.users.find(user => user.id === id);
     }

     create(user: User): void {
       this.users.push(user);
     }

     update(id: number, updatedUser: User): void {
       const userIndex = this.users.findIndex(user => user.id === id);
       if (userIndex > -1) {
         this.users[userIndex] = updatedUser;
       }
     }

     delete(id: number): void {
       this.users = this.users.filter(user => user.id !== id);
     }
   }
Enter fullscreen mode Exit fullscreen mode
  1. Update Users Controller: Open src/users/users.controller.ts and implement the endpoints.
   import { Controller, Get, Post, Body, Param, Put, Delete } from '@nestjs/common';
   import { UsersService } from './users.service';

   @Controller('users')
   export class UsersController {
     constructor(private readonly usersService: UsersService) {}

     @Get()
     findAll() {
       return this.usersService.findAll();
     }

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

     @Post()
     create(@Body() user: { id: number; name: string; age: number }) {
       this.usersService.create(user);
     }

     @Put(':id')
     update(@Param('id') id: number, @Body() user: { id: number; name: string; age: number }) {
       this.usersService.update(id, user);
     }

     @Delete(':id')
     remove(@Param('id') id: number) {
       this.usersService.delete(id);
     }
   }
Enter fullscreen mode Exit fullscreen mode
  1. Update Users Module: Open src/users/users.module.ts and import the service and controller.
   import { Module } from '@nestjs/common';
   import { UsersService } from './users.service';
   import { UsersController } from './users.controller';

   @Module({
     controllers: [UsersController],
     providers: [UsersService],
   })
   export class UsersModule {}
Enter fullscreen mode Exit fullscreen mode
  1. Integrate Users Module in App Module: Open src/app.module.ts and import the UsersModule.
   import { Module } from '@nestjs/common';
   import { AppController } from './app.controller';
   import { AppService } from './app.service';
   import { UsersModule } from './users/users.module';

   @Module({
     imports: [UsersModule],
     controllers: [AppController],
     providers: [AppService],
   })
   export class AppModule {}
Enter fullscreen mode Exit fullscreen mode
  1. Run the Application:
   npm run start
Enter fullscreen mode Exit fullscreen mode
  1. Test the Application: Use a tool like Postman or curl to test the CRUD endpoints.

Step 6: Learn More Advanced NestJS Features

  1. Middleware:
    Middleware functions are executed before the route handler.

    • Example:
     import { Injectable, NestMiddleware } from '@nestjs/common';
     import { Request, Response, NextFunction } from 'express';
    
     @Injectable()
     export class LoggerMiddleware implements NestMiddleware {
       use(req: Request, res: Response, next: NextFunction) {
         console.log(`Request...`);
         next();
       }
     }
    
  2. Interceptors:
    Interceptors are used to transform the response or handle exceptions.

    • Example:
     import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
     import { Observable } from 'rxjs';
     import { map } from 'rxjs/operators';
    
     @Injectable()
     export class TransformInterceptor implements NestInterceptor {
       intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
         return next.handle().pipe(map(data => ({ data })));
       }
     }
    
  3. Guards:
    Guards are used for authentication and authorization.

    • Example:
     import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
     import { Observable } from 'rxjs';
    
     @Injectable()
     export class AuthGuard implements CanActivate {
       canActivate(
         context: ExecutionContext,
       ): boolean | Promise<boolean> | Observable<boolean> {
         const request = context.switchToHttp().getRequest();
         return validateRequest(request);
       }
     }
    
  4. Pipes:
    Pipes are used to transform and validate data.

    • Example:
     import { PipeTransform, Injectable, ArgumentMetadata, BadRequestException } from '@nestjs/common';
    
     @Injectable()
     export class ParseIntPipe implements PipeTransform<string, number> {
       transform(value: string, metadata: ArgumentMetadata): number {
         const val = parseInt(value, 10);
         if (isNaN(val)) {
           throw new BadRequestException('Validation failed');
         }
         return val;
       }
     }
    

Step 7: Testing and Debugging

  1. Unit Testing:

    • NestJS uses Jest for unit testing.
    • Example:
     import { Test, TestingModule } from '@nestjs/testing';
     import { UsersService } from './users.service';
    
     describe('UsersService', () => {
       let service: UsersService;
    
       beforeEach(async () => {
         const module: TestingModule = await Test.createTestingModule({
           providers: [Users
    

Service],
}).compile();

     service = module.get<UsersService>(UsersService);
   });

   it('should be defined', () => {
     expect(service).toBeDefined();
   });
 });
 ```
Enter fullscreen mode Exit fullscreen mode
  1. End-to-End Testing:

    • Use Supertest for end-to-end testing.
    • Example:
     import { Test, TestingModule } from '@nestjs/testing';
     import { INestApplication } from '@nestjs/common';
     import * as request from 'supertest';
     import { AppModule } from './../src/app.module';
    
     describe('AppController (e2e)', () => {
       let app: INestApplication;
    
       beforeEach(async () => {
         const moduleFixture: TestingModule = await Test.createTestingModule({
           imports: [AppModule],
         }).compile();
    
         app = moduleFixture.createNestApplication();
         await app.init();
       });
    
       it('/ (GET)', () => {
         return request(app.getHttpServer())
           .get('/')
           .expect(200)
           .expect('Hello World!');
       });
     });
    

Step 8: Learning Resources

  1. Official Documentation:

  2. Online Courses:

  3. Books:

    • "Mastering NestJS" by Kamil Myśliwiec
  4. Tutorials and Articles:

  5. Community and Forums:

Step 9: Build Real-World Projects

  1. Choose Real-World Projects:

    • Build applications like an e-commerce platform, blog, or social media app.
  2. Contribute to Open Source:

    • Contribute to open source NestJS projects on GitHub.

Step 10: Stay Updated

  1. Follow NestJS Updates:
    • Follow the NestJS blog
    • Join NestJS newsletters
    • Attend NestJS conferences and meetups

By following this structured guide and practicing regularly, you'll build up your knowledge and skills in NestJS, enabling you to create powerful and efficient server-side applications. If you have any specific questions or need further details on any step, feel free to ask!

If you enjoy my content and would like to support my work, you can buy me a coffee. Your support is greatly appreciated!

Disclaimer: This content is generated by AI.

Top comments (0)