If Express is the “light cavalry” of Node.js, then NestJS is the “regular army” of Node.js. It brings backend development into the “engineering” era.
What is NestJS?#
NestJS is an enterprise-grade Node.js framework created by Kamil Myśliwiec in 2017. Its core characteristic is: Using Angular’s architectural thinking to build scalable Node.js applications with TypeScript.
Understanding Through Analogy#
| Aspect | Express | NestJS |
|---|---|---|
| Style | Free and loose | Modular system |
| Types | JavaScript primarily | TypeScript first |
| Dependency injection | None | Full support |
| Decorators | None | Widely used |
| Like | Raw apartment | Finished apartment |
NestJS = Angular’s architecture + Express’s flexibility + TypeScript’s type safety
Core Features#
1. Modular Architecture: Building Like Puzzles#
The core of NestJS is the module system:
// user.module.ts
@Module({
imports: [TypeOrmModule.forFeature([User])],
controllers: [UserController],
providers: [UserService],
exports: [UserService],
})
export class UserModule {}// app.module.ts
@Module({
imports: [
UserModule,
AuthModule,
ConfigModule,
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}2. Dependency Injection: Control Inversion#
NestJS implements a complete dependency injection (DI) system:
// user.service.ts
@Injectable()
export class UserService {
constructor(
private readonly userRepository: UserRepository,
private readonly logger: Logger,
) {}
async findAll(): Promise<User[]> {
return this.userRepository.find();
}
async create(createUserDto: CreateUserDto): Promise<User> {
const user = this.userRepository.create(createUserDto);
return this.userRepository.save(user);
}
}// user.controller.ts
@Controller('users')
export class UserController {
constructor(private readonly userService: UserService) {}
@Get()
async findAll(): Promise<User[]> {
return this.userService.findAll();
}
@Post()
async create(@Body() createUserDto: CreateUserDto): Promise<User> {
return this.userService.create(createUserDto);
}
@Get(':id')
async findOne(@Param('id') id: string): Promise<User> {
return this.userService.findOne(id);
}
}3. Decorator-Based Routing: Declarative Definition#
NestJS uses decorators to define routes, clear and intuitive:
@Controller('api')
export class AppController {
@Get('hello')
getHello(): string {
return 'Hello World!';
}
@Post('users')
@UseGuards(AuthGuard)
@HttpCode(201)
async create(@Body() createDto: CreateDto, @Req() req: Request) {
return this.service.create(createDto, req.user);
}
@Get('users/:id')
@UseGuards(AuthGuard)
async findOne(@Param('id', ParseIntPipe) id: number) {
return this.service.findOne(id);
}
}4. Guards, Interceptors, Pipes: Enhanced Functionality#
Guards: Permission Control#
@Injectable()
export class AuthGuard implements CanActivate {
canActivate(context: ExecutionContext): boolean {
const request = context.switchToHttp().getRequest();
return request.headers.authorization?.startsWith('Bearer ');
}
}Pipes: Data Transformation and Validation#
@Injectable()
export class ValidationPipe implements PipeTransform {
transform(value: any, metadata: ArgumentMetadata) {
if (metadata.type === 'body') {
// Validation logic
}
return value;
}
}Interceptors: Unified Processing#
@Injectable()
export class LoggingInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
const now = Date.now();
return next
.handle()
.pipe(
tap(() => console.log(`After... ${Date.now() - now}ms`)),
);
}
}5. Decorator Details#
NestJS extensively uses decorators:
| Decorator | Purpose |
|---|---|
@Controller() | Define controller |
@Injectable() | Define injectable service |
@Module() | Define module |
@Get(), @Post() etc. | Define route methods |
@Body(), @Param() etc. | Get request data |
@UseGuards() | Use guards |
@UseInterceptors() | Use interceptors |
@UsePipes() | Use pipes |
6. Database Integration#
NestJS can integrate with multiple databases:
// Using TypeORM
@Module({
imports: [
TypeOrmModule.forRoot({
type: 'mysql',
host: 'localhost',
port: 3306,
username: 'root',
password: 'password',
database: 'test',
entities: [User],
synchronize: true,
}),
TypeOrmModule.forFeature([User]),
],
})
export class AppModule {}Why is NestJS So Popular?#
1. Enterprise-Grade Architecture#
NestJS provides complete engineering architecture:
- Modular system
- Dependency injection
- Clear code organization
- Suitable for large projects
2. TypeScript First#
Fully based on TypeScript:
- Complete type support
- Better code suggestions
- Compile-time error checking
3. Rich Ecosystem#
- Database: TypeORM, Prisma, Mongoose
- Validation: class-validator
- Documentation: Swagger/OpenAPI
- Testing: Jest
- WebSocket: Socket.io
4. Similar to Angular#
If you’re familiar with Angular, learning NestJS is very easy:
- Same module system
- Same dependency injection
- Same decorator style
Use Cases#
| Scenario | Suitability | Notes |
|---|---|---|
| Enterprise backend | ⭐⭐⭐⭐⭐ | Complete architecture support |
| Microservices | ⭐⭐⭐⭐⭐ | Built-in microservices support |
| REST API | ⭐⭐⭐⭐⭐ | Complete solution |
| Large applications | ⭐⭐⭐⭐⭐ | Modular architecture |
| TypeScript projects | ⭐⭐⭐⭐⭐ | Native support |
| Simple tools | ⭐⭐ | Somewhat “heavy” |
Learning Path#
Beginner (2 weeks)#
- Master TypeScript
- Understand NestJS project structure
- Learn basic usage of modules, controllers, services
- Master dependency injection
Intermediate (2-3 weeks)#
- Master guards, interceptors, pipes
- Learn database integration (TypeORM/Prisma)
- Master validation and error handling
- Understand decorator principles
Advanced (continuous learning)#
- Microservices development
- GraphQL support
- WebSocket
- Performance optimization
NestJS vs Express Comparison#
| Feature | NestJS | Express |
|---|---|---|
| Architecture | Modular | Free |
| Language | TypeScript | JavaScript/TS |
| Dependency injection | Native support | None |
| Decorators | Widely used | None |
| Learning curve | Relatively steep | Flat |
| Best for | Large applications | Small projects |
| Code organization | Convention first | Free |
Common Commands#
# Install NestJS CLI
npm i -g @nestjs/cli
# Create new project
nest new my-project
# Generate module
nest g module user
# Generate controller
nest g controller user
# Generate service
nest g service user
# Generate resource (CRUD)
nest g resource userSummary#
NestJS brings enterprise-grade development experience to Node.js:
- Modular architecture—Clear code organization
- Dependency injection—Decoupling and testability
- Decorator-based routing—Declarative definition
- TypeScript first—Type safety
- Rich ecosystem—Integrate various databases and tools
If you need to build large Node.js applications, especially enterprise projects, NestJS is the best choice. It makes Node.js development “standardized.”
Next up: NestJS is the “regular army,” while Express is the “light cavalry”—the most classic and flexible framework in Node.js. Let’s dive into this “old friend of Node.js” in the next article.
