NestJS(基于 Express 的现代化框架)
NestJS 是一个基于 Express.js 的现代化框架,同时支持 Fastify 作为底层 HTTP 平台。它结合了面向对象编程(OOP)、函数式编程(FP)和响应式编程(RxJS),提供了一个高度模块化、可扩展且易于维护的开发环境,非常适合构建大型企业级应用。
以下是关于 NestJS 的详细介绍以及如何高效使用它的指南。
1. 为什么选择 NestJS?
NestJS 在 Express.js 的基础上进行了封装和增强,解决了传统 Express.js 开发中的一些痛点:
(1) 模块化架构
- NestJS 提供了一套模块化的结构,代码组织更加清晰。
- 通过
@Module
装饰器定义模块,方便管理依赖关系。
(2) 内置依赖注入(DI)
- 借鉴 Angular 的依赖注入机制,简化了服务、控制器和其他组件之间的依赖管理。
(3) TypeScript 支持
- 完全基于 TypeScript 构建,提供了强大的类型检查和开发体验。
(4) 内置功能丰富
- 内置支持 GraphQL、WebSocket、微服务、日志记录等高级功能。
- 提供开箱即用的中间件、拦截器、管道和守卫,提升开发效率。
(5) 高度可扩展
- 可以轻松集成第三方库或自定义功能。
- 支持多种数据库(如 MongoDB、PostgreSQL、MySQL)和 ORM(如 TypeORM、Mongoose)。
2. NestJS 的核心概念
NestJS 的设计遵循清晰的分层架构,主要包括以下核心概念:
(1) 模块(Module)
- 模块是 NestJS 应用的基本单元,用于组织相关的功能。
- 使用
@Module
装饰器定义模块。
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) 控制器(Controller)
- 控制器负责处理传入的 HTTP 请求并返回响应。
- 使用
@Controller
和路由装饰器(如@Get
,@Post
)定义路由。
import { Controller, Get } from '@nestjs/common';
@Controller('users')
export class UsersController {
@Get()
findAll() {
return 'This action returns all users';
}
}
(3) 服务(Service)
- 服务用于封装业务逻辑,通常通过依赖注入注入到控制器中。
- 使用
@Injectable
装饰器定义服务。
import { Injectable } from '@nestjs/common';
@Injectable()
export class UsersService {
findAll() {
return [{ id: 1, name: 'John Doe' }];
}
}
(4) 管道(Pipe)
- 管道用于对请求数据进行验证和转换。
- 内置管道如
ValidationPipe
,也可以自定义管道。
import { PipeTransform, Injectable, ArgumentMetadata } from '@nestjs/common';
@Injectable()
export class CustomPipe implements PipeTransform {
transform(value: any, metadata: ArgumentMetadata) {
return value.toUpperCase(); // 示例:将输入值转换为大写
}
}
(5) 守卫(Guard)
- 守卫用于保护路由,控制访问权限。
- 常用于身份验证和授权。
import { CanActivate, ExecutionContext } from '@nestjs/common';
@Injectable()
export class AuthGuard implements CanActivate {
canActivate(context: ExecutionContext) {
const request = context.switchToHttp().getRequest();
return request.isAuthenticated(); // 示例:检查用户是否已认证
}
}
3. 使用 NestJS 构建 RESTful API
以下是一个简单的博客系统 API 示例,展示如何使用 NestJS 实现增删改查操作。
(1) 初始化项目
使用 Nest CLI 初始化项目:
npm install -g @nestjs/cli
nest new blog-api
cd blog-api
安装依赖:
npm install @nestjs/typeorm typeorm pg
(2) 配置数据库
在 app.module.ts
中配置 TypeORM 和 PostgreSQL 数据库连接。
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
@Module({
imports: [
TypeOrmModule.forRoot({
type: 'postgres',
host: 'localhost',
port: 5432,
username: 'postgres',
password: 'password',
database: 'blog',
entities: [],
synchronize: true,
}),
],
})
export class AppModule {}
(3) 创建实体
定义博客文章的实体模型。
import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm';
@Entity()
export class Blog {
@PrimaryGeneratedColumn()
id: number;
@Column()
title: string;
@Column()
content: string;
}
(4) 创建服务
实现博客文章的 CRUD 逻辑。
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Blog } from './blog.entity';
@Injectable()
export class BlogsService {
constructor(
@InjectRepository(Blog)
private blogsRepository: Repository<Blog>,
) {}
findAll(): Promise<Blog[]> {
return this.blogsRepository.find();
}
findOne(id: number): Promise<Blog> {
return this.blogsRepository.findOneBy({ id });
}
async create(blogData: Partial<Blog>): Promise<Blog> {
const blog = this.blogsRepository.create(blogData);
return this.blogsRepository.save(blog);
}
async update(id: number, blogData: Partial<Blog>): Promise<Blog> {
await this.blogsRepository.update(id, blogData);
return this.findOne(id);
}
async remove(id: number): Promise<void> {
await this.blogsRepository.delete(id);
}
}
(5) 创建控制器
定义路由和处理逻辑。
import { Controller, Get, Post, Body, Param, Put, Delete } from '@nestjs/common';
import { BlogsService } from './blogs.service';
import { Blog } from './blog.entity';
@Controller('blogs')
export class BlogsController {
constructor(private readonly blogsService: BlogsService) {}
@Get()
findAll(): Promise<Blog[]> {
return this.blogsService.findAll();
}
@Get(':id')
findOne(@Param('id') id: number): Promise<Blog> {
return this.blogsService.findOne(id);
}
@Post()
create(@Body() blogData: Blog): Promise<Blog> {
return this.blogsService.create(blogData);
}
@Put(':id')
update(@Param('id') id: number, @Body() blogData: Blog): Promise<Blog> {
return this.blogsService.update(id, blogData);
}
@Delete(':id')
remove(@Param('id') id: number): Promise<void> {
return this.blogsService.remove(id);
}
}
(6) 启动服务器
运行以下命令启动服务器:
npm run start
4. NestJS 的扩展与优化
为了进一步提升项目的性能和可维护性,可以结合以下工具和最佳实践:
(1) 使用 GraphQL
NestJS 提供了对 GraphQL 的原生支持,适合需要复杂查询的应用。
npm install @nestjs/graphql graphql-tools graphql apollo-server-express
(2) 微服务支持
NestJS 支持多种微服务传输协议(如 TCP、Redis、MQTT),适合分布式系统。
import { Module } from '@nestjs/common';
import { ClientsModule, Transport } from '@nestjs/microservices';
@Module({
imports: [
ClientsModule.register([
{
name: 'MATH_SERVICE',
transport: Transport.TCP,
options: { host: 'localhost', port: 3001 },
},
]),
],
})
export class AppModule {}
(3) 日志记录
使用 @nestjs/common
提供的内置日志工具,或集成第三方库如 winston
。
5. 总结
NestJS 是一个现代化的后端框架,结合了 Express.js 的灵活性和 TypeScript 的强类型特性,非常适合构建大型企业级应用。它的模块化架构、依赖注入和丰富的内置功能使其成为 Express.js 的强大替代品。