How to learn Nest JS?
Nadim Chowdhury
Posted on June 4, 2024
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.
-
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.
-
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
Install Node.js:
Download and install Node.js from nodejs.org.Install Nest CLI:
The Nest CLI is a powerful tool to initialize, develop, and maintain NestJS applications.
npm install -g @nestjs/cli
Step 3: Create a New NestJS Project
- Create a New Project:
nest new my-nestjs-app
cd my-nestjs-app
- Run the Application:
npm run start
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
Step 5: Learn the Basics of NestJS
-
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 {}
-
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(); } }
-
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.
- Generate a New Module:
nest generate module users
- Generate a Controller:
nest generate controller users
- Generate a Service:
nest generate service users
-
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);
}
}
-
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);
}
}
-
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 {}
-
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 {}
- Run the Application:
npm run start
- Test the Application: Use a tool like Postman or curl to test the CRUD endpoints.
Step 7: Learn More Advanced NestJS Features
-
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(); } }
-
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 }))); } }
-
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); } }
-
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
-
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();
});
});
```
-
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
-
Official Documentation:
-
Online Courses:
-
Books:
- "Mastering NestJS" by Kamil Myśliwiec
-
Tutorials and Articles:
-
Community and Forums:
Step 10: Build Real-World Projects
-
Choose Real-World Projects:
- Build applications like an e-commerce platform, blog, or social media app.
-
Contribute to Open Source:
- Contribute to open source NestJS projects on GitHub.
Step 11: Stay Updated
-
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
Install Node.js:
Download and install Node.js from nodejs.org.Install Nest CLI:
The Nest CLI is a powerful tool to initialize, develop, and maintain NestJS applications.
npm install -g @nestjs/cli
Step 2: Create a New NestJS Project
- Create a New Project:
nest new my-nestjs-app
cd my-nestjs-app
- Run the Application:
npm run start
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
Step 4: Learn the Basics of NestJS
-
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();
-
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 {}
-
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(); } }
-
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.
- Generate a New Module:
nest generate module users
- Generate a Controller:
nest generate controller users
- Generate a Service:
nest generate service users
-
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);
}
}
-
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);
}
}
-
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 {}
-
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 {}
- Run the Application:
npm run start
- Test the Application: Use a tool like Postman or curl to test the CRUD endpoints.
Step 6: Learn More Advanced NestJS Features
-
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(); } }
-
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 }))); } }
-
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); } }
-
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
-
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();
});
});
```
-
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
-
Official Documentation:
-
Online Courses:
-
Books:
- "Mastering NestJS" by Kamil Myśliwiec
-
Tutorials and Articles:
-
Community and Forums:
Step 9: Build Real-World Projects
-
Choose Real-World Projects:
- Build applications like an e-commerce platform, blog, or social media app.
-
Contribute to Open Source:
- Contribute to open source NestJS projects on GitHub.
Step 10: Stay Updated
-
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.
Posted on June 4, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.