Skip to content

NestJS 后端框架知识点

一、NestJS 简介

1. 什么是 NestJS

NestJS 是一个用于构建高效、可扩展的 Node.js 服务器端应用程序的渐进式框架。它基于 TypeScript 构建,结合了 OOP(面向对象编程)、FP(函数式编程)和 FRP(函数响应式编程)的元素。NestJS 提供了一种模块化的方式来组织代码,使开发者能够构建可维护和可测试的应用程序。

2. NestJS 的特点

  • TypeScript 支持:内置 TypeScript 支持,提供类型安全
  • 模块化架构:基于模块的架构,便于代码组织和维护
  • 依赖注入:内置依赖注入容器,简化组件之间的依赖管理
  • 装饰器语法:使用装饰器语法,简化代码编写
  • 中间件支持:支持全局和路由级中间件
  • 异常过滤:统一的异常处理机制
  • 管道:用于数据验证和转换
  • 守卫:用于权限控制和认证
  • 拦截器:用于请求/响应的预处理和后处理
  • 与 Express 和 Fastify 兼容:底层可以使用 Express 或 Fastify 作为 HTTP 服务器
  • 强大的 CLI:提供命令行工具,简化项目创建和管理
  • 丰富的生态系统:提供多种模块和集成

3. NestJS 的优势

  • 代码组织:模块化架构使代码更易于组织和维护
  • 类型安全:TypeScript 提供编译时类型检查,减少运行时错误
  • 可测试性:依赖注入使测试更加容易
  • 可扩展性:模块化设计使应用程序易于扩展
  • 社区活跃:拥有活跃的社区和丰富的文档
  • 企业级应用:适合构建大型企业级应用

二、NestJS 的核心概念

1. 模块 (Module)

模块是 NestJS 应用程序的基本组织单位,用于组织代码并定义组件之间的关系。每个模块都由 @Module() 装饰器标记,包含控制器、提供者和导入的模块。

模块的结构

  • controllers:处理 HTTP 请求和响应
  • providers:服务、仓库等可注入的依赖
  • imports:导入其他模块
  • exports:导出模块中的提供者,供其他模块使用

根模块

根模块是应用程序的入口点,通常命名为 AppModule

2. 控制器 (Controller)

控制器负责处理 HTTP 请求,路由请求到相应的处理方法,并返回响应。控制器使用 @Controller() 装饰器标记,方法使用 HTTP 方法装饰器(如 @Get()@Post() 等)标记。

3. 提供者 (Provider)

提供者是 NestJS 中的核心概念,包括服务、仓库、工厂等。提供者可以被注入到其他组件中,使用 @Injectable() 装饰器标记。

4. 服务 (Service)

服务是提供者的一种,用于封装业务逻辑。服务通常被注入到控制器中,处理具体的业务操作。

5. 中间件 (Middleware)

中间件是在路由处理之前或之后执行的函数,用于处理请求和响应。中间件可以是全局的或路由级的。

6. 管道 (Pipe)

管道用于数据验证和转换,在请求到达控制器之前执行。管道可以用于验证请求体、查询参数等。

7. 守卫 (Guard)

守卫用于权限控制和认证,在控制器方法执行之前执行。守卫可以用于验证用户身份、检查权限等。

8. 拦截器 (Interceptor)

拦截器用于请求/响应的预处理和后处理,如日志记录、异常处理、响应转换等。

9. 异常过滤器 (Exception Filter)

异常过滤器用于统一处理应用程序中的异常,将异常转换为适当的 HTTP 响应。

10. 自定义装饰器 (Custom Decorator)

NestJS 允许创建自定义装饰器,用于增强代码的可读性和功能。

三、NestJS 项目结构

1. 典型的项目结构

src/
├── app.module.ts        # 根模块
├── app.controller.ts    # 根控制器
├── app.service.ts       # 根服务
├── app.controller.spec.ts  # 控制器测试
├── app.service.spec.ts     # 服务测试
├── main.ts              # 应用程序入口
└── modules/             # 功能模块
    ├── users/
    │   ├── users.module.ts
    │   ├── users.controller.ts
    │   ├── users.service.ts
    │   ├── users.entity.ts
    │   └── dto/
    │       ├── create-user.dto.ts
    │       └── update-user.dto.ts
    └── auth/
        ├── auth.module.ts
        ├── auth.controller.ts
        ├── auth.service.ts
        └── strategies/
            └── jwt.strategy.ts

2. 目录说明

  • src/:源代码目录
  • main.ts:应用程序入口,创建和启动 Nest 应用
  • app.module.ts:根模块,组织整个应用的模块结构
  • app.controller.ts:根控制器,处理根路径的请求
  • app.service.ts:根服务,提供基础服务
  • modules/:功能模块目录,按业务功能划分
  • dto/:数据传输对象,用于请求和响应的数据结构
  • entity/:数据库实体,映射数据库表结构
  • strategies/:认证策略,如 JWT 策略

四、NestJS 常用功能

1. 路由

NestJS 使用装饰器定义路由,支持参数路由、查询参数、请求体等。

基本路由

typescript
@Controller('users')
export class UsersController {
  @Get()
  findAll() {
    return 'All users';
  }

  @Get(':id')
  findOne(@Param('id') id: string) {
    return `User ${id}`;
  }

  @Post()
  create(@Body() createUserDto: CreateUserDto) {
    return 'Create user';
  }

  @Put(':id')
  update(@Param('id') id: string, @Body() updateUserDto: UpdateUserDto) {
    return `Update user ${id}`;
  }

  @Delete(':id')
  remove(@Param('id') id: string) {
    return `Remove user ${id}`;
  }
}

2. 依赖注入

NestJS 使用依赖注入容器管理组件之间的依赖关系。

服务注入

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

  findAll() {
    return this.users;
  }

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

  create(user: CreateUserDto) {
    this.users.push(user);
    return user;
  }
}

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

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

3. 数据验证

NestJS 使用管道进行数据验证,通常结合 class-validator 库。

DTO 定义

typescript
import { IsString, IsEmail, IsNotEmpty } from 'class-validator';

export class CreateUserDto {
  @IsString()
  @IsNotEmpty()
  name: string;

  @IsEmail()
  email: string;

  @IsString()
  @IsNotEmpty()
  password: string;
}

使用管道

typescript
@Post()
create(@Body() createUserDto: CreateUserDto) {
  return this.usersService.create(createUserDto);
}

4. 认证与授权

NestJS 支持多种认证策略,如 JWT、OAuth 等。

JWT 认证

typescript
// auth.module.ts
import { Module } from '@nestjs/common';
import { JwtModule } from '@nestjs/jwt';
import { AuthService } from './auth.service';
import { AuthController } from './auth.controller';
import { JwtStrategy } from './strategies/jwt.strategy';

@Module({
  imports: [
    JwtModule.register({
      secret: 'secretKey',
      signOptions: { expiresIn: '1h' },
    }),
  ],
  providers: [AuthService, JwtStrategy],
  controllers: [AuthController],
})
export class AuthModule {}

// jwt.strategy.ts
import { Injectable } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { ExtractJwt, Strategy } from 'passport-jwt';

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
  constructor() {
    super({
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      ignoreExpiration: false,
      secretOrKey: 'secretKey',
    });
  }

  async validate(payload: any) {
    return { userId: payload.sub, username: payload.username };
  }
}

// 使用守卫
import { UseGuards } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';

@Controller('users')
export class UsersController {
  @UseGuards(AuthGuard('jwt'))
  @Get()
  findAll() {
    return this.usersService.findAll();
  }
}

5. 数据库集成

NestJS 支持多种数据库,如 PostgreSQL、MySQL、MongoDB 等。

TypeORM 集成

typescript
// app.module.ts
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { UsersModule } from './users/users.module';

@Module({
  imports: [
    TypeOrmModule.forRoot({
      type: 'postgres',
      host: 'localhost',
      port: 5432,
      username: 'postgres',
      password: 'password',
      database: 'nestjs',
      entities: [__dirname + '/**/*.entity{.ts,.js}'],
      synchronize: true,
    }),
    UsersModule,
  ],
})
export class AppModule {}

// users.entity.ts
import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';

@Entity()
export class User {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  name: string;

  @Column()
  email: string;

  @Column()
  password: string;
}

// users.module.ts
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { UsersController } from './users.controller';
import { UsersService } from './users.service';
import { User } from './users.entity';

@Module({
  imports: [TypeOrmModule.forFeature([User])],
  controllers: [UsersController],
  providers: [UsersService],
})
export class UsersModule {}

6. 配置管理

NestJS 提供了配置模块,用于管理应用程序配置。

配置模块使用

typescript
// app.module.ts
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';

@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
    }),
  ],
})
export class AppModule {}

// 使用配置
import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';

@Injectable()
export class AppService {
  constructor(private configService: ConfigService) {}

  getDatabaseHost() {
    return this.configService.get('DATABASE_HOST');
  }
}

7. 日志

NestJS 内置了日志系统,支持不同级别的日志。

日志使用

typescript
import { Injectable, Logger } from '@nestjs/common';

@Injectable()
export class UsersService {
  private readonly logger = new Logger(UsersService.name);

  findAll() {
    this.logger.log('Finding all users');
    return this.users;
  }
}

8. 测试

NestJS 支持单元测试和集成测试,使用 Jest 作为测试框架。

测试示例

typescript
// users.service.spec.ts
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();
  });

  it('should return all users', () => {
    expect(service.findAll()).toEqual([]);
  });
});

五、NestJS 最佳实践

1. 代码组织

  • 模块化设计:按功能划分模块,每个模块包含相关的控制器、服务和实体
  • 单一职责:每个组件只负责一个功能
  • 依赖注入:使用依赖注入管理组件之间的依赖
  • DTO 模式:使用 DTO 定义请求和响应的数据结构

2. 性能优化

  • 数据库优化:使用索引、批量操作、连接池等
  • 缓存:使用 Redis 等缓存机制
  • 异步操作:使用 async/await 和 Promise
  • 代码分割:按需加载模块

3. 安全

  • 认证与授权:使用 JWT 或 OAuth 进行认证
  • 输入验证:使用管道进行数据验证
  • CSRF 保护:防止跨站请求伪造
  • CORS 配置:正确配置跨域资源共享
  • 密码加密:使用 bcrypt 等库加密密码

4. 部署

  • 容器化:使用 Docker 容器化应用
  • 环境变量:使用环境变量管理配置
  • CI/CD:使用 GitHub Actions 等工具实现持续集成和部署
  • 监控:使用 Prometheus、Grafana 等工具监控应用

六、NestJS 生态系统

1. 核心模块

  • @nestjs/common:核心功能模块
  • @nestjs/core:核心运行时
  • @nestjs/platform-express:Express 适配器
  • @nestjs/platform-fastify:Fastify 适配器

2. 常用模块

  • @nestjs/config:配置管理
  • @nestjs/jwt:JWT 认证
  • @nestjs/passport:Passport 集成
  • @nestjs/typeorm:TypeORM 集成
  • @nestjs/mongoose:MongoDB 集成
  • @nestjs/serve-static:静态文件服务
  • @nestjs/swagger:API 文档

3. 工具

  • Nest CLI:命令行工具,用于创建和管理项目
  • Swagger:API 文档生成工具
  • TypeORM:ORM 框架,用于数据库操作
  • Mongoose:MongoDB ODM
  • Passport:认证中间件

4. 社区资源

七、NestJS 与其他框架的比较

1. NestJS vs Express

  • Express:轻量级框架,灵活性高,适合小型应用
  • NestJS:基于 Express,提供更结构化的架构,适合大型应用

2. NestJS vs Koa

  • Koa:Express 的继任者,更轻量,使用 async/await
  • NestJS:提供更完整的功能集和更结构化的架构

3. NestJS vs AdonisJS

  • AdonisJS:全功能框架,提供 ORM、认证等
  • NestJS:更现代,基于 TypeScript,生态系统更丰富

八、总结

NestJS 是一个功能强大、结构清晰的 Node.js 后端框架,它结合了 TypeScript 的类型安全和模块化架构的优势,使开发者能够构建可维护、可测试和可扩展的应用程序。通过掌握 NestJS 的核心概念和最佳实践,你可以构建高质量的后端服务,满足现代应用的需求。

作为一名后端开发者,学习 NestJS 将为你提供一种现代化的开发方式,帮助你更高效地构建和维护后端应用。NestJS 的生态系统不断发展,社区活跃,是构建企业级应用的理想选择。

Released under the MIT License.