DEV Community

Nadim Chowdhury
Nadim Chowdhury

Posted 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!

Disclaimer: This content is generated by AI.

Top comments (0)