NestJS 全栈深入课程大纲

3 阅读43分钟

20 节课系统掌握 NestJS 框架,从入门到架构设计。 基于 NestJS v11 官方文档全部 142 页 + 框架源码 42,000 行 TypeScript 设计。


课程设计原则

受众分层:每节课包含五个层次的内容,不同水平的学员在同一节课中各取所需。

标识层次画像目标
[基础]入门有 Node.js 基础,首次接触 NestJS能用框架写出可运行的代码
[中阶]熟练能用 NestJS 完成业务开发掌握最佳实践,写出规范代码
[高阶]深入1 年以上 NestJS 经验理解框架内部机制,能扩展框架
[资深]源码希望成为框架贡献者或深度定制者能读懂并修改框架源码
[架构]设计技术负责人、架构师能基于 NestJS 做技术选型和系统设计

知识依赖图

第一阶段:核心基础(第1-4课)
 第1课 ─→ 第2课 ─→ 第3课 ─→ 第4课

第二阶段:请求管线(第5-8课)
                              │
              ┌───────────────┤
              ▼               ▼
           第5课            第6课
              │               │
              ▼               ▼
           第7课            第8课

第三阶段:DI 深入(第9课)
              │               │
              └───────┬───────┘
                      ▼
                   第9课

第四阶段:数据与安全(第10-12课)
                      │
              ┌───────┤
              ▼       ▼
           第10课   第11课 ─→ 第12课

第五阶段:实用技术(第13-15课)
              │
    ┌─────────┼─────────┐
    ▼         ▼         ▼
 第13课    第14课    第15课

第六阶段:通信与 API(第16-19课)
    │         │         │
    └─────────┼─────────┘
              ▼
           第16课 ─→ 第17课
              │
           第18课 ─→ 第19课

第七阶段:生产(第20课)
              │
              ▼
           第20课

负载均衡:每节课覆盖 5-10 页文档、3-6 个核心主题,确保节奏均匀。

阶段课程覆盖文档页数核心主题数
核心基础第1-4课4+2+3+4 = 133+3+4+5 = 15
请求管线第5-8课3+2+3+3 = 114+4+5+4 = 17
DI 深入第9课56
数据与安全第10-12课7+4+5 = 165+5+5 = 15
实用技术第13-15课5+3+7 = 155+3+6 = 14
通信与 API第16-19课6+12+18+10 = 464+5+6+5 = 20
生产第20课15+6

第一课:走进 NestJS — 理念、环境与第一个应用

覆盖文档:Introduction, First Steps, CLI Overview, CLI Scripts 前置知识:Node.js 基础, TypeScript 基础

课程内容

[基础] 从零创建项目

  • NestJS 是什么:基于 Node.js 的渐进式服务端框架
  • 与 Express/Koa/Fastify 的关系:NestJS 是架构层,Express/Fastify 是 HTTP 引擎
  • 环境准备:Node.js >= 20, Nest CLI 安装
  • nest new project-name 创建项目
  • 项目目录结构解析:main.tsapp.module.tsapp.controller.tsapp.service.ts
  • NestFactory.create(AppModule)app.listen(3000)
  • 启动与验证:npm run start:dev,访问 http://localhost:3000
  • CLI 常用命令:nest generate(18 种 schematic),nest buildnest start

[中阶] 工程化配置

  • TypeScript 严格模式:nest new --strict
  • SWC 编译器加速:npm run start -- -b swc,20x 编译提速
  • ESLint + Prettier 代码规范
  • 热重载配置(HMR):webpack + RunScriptWebpackPlugin
  • nest-cli.json 关键配置项:compilerOptionsgenerateOptions

[高阶] 平台选择与多平台抽象

  • Express vs Fastify 对比:生态 vs 性能
  • NestFactory.create<NestExpressApplication>NestFactory.create<NestFastifyApplication> 的区别
  • abortOnError 选项的作用
  • 平台无关性设计思想:同一套业务逻辑可以运行在 HTTP/WebSocket/微服务/GraphQL 上

[资深] 源码:NestFactory 启动流程

  • 入口文件:packages/core/nest-factory.ts
  • create() 方法的完整流程:
    1. 创建 NestContainer(DI 容器)
    2. 初始化 DependenciesScanner
    3. 初始化 InstanceLoader
    4. 初始化 RoutesResolver
    5. 调用生命周期钩子
  • ExceptionsZone 的作用:全局异常捕获区

[架构] 技术选型决策

  • NestJS 适用场景:企业级 API、微服务、BFF 层、全栈应用
  • 不适用场景:极简 Serverless 函数、纯静态站点
  • 与 Spring Boot 的架构对比:同样的 IoC/DI 思想,不同的语言生态
  • Monorepo vs 多仓:nest g app 转换 Monorepo,nest g library 创建共享库
  • 团队接入 NestJS 的成本评估

课后实践

  • nest new 创建项目,确认 Hello World 运行正常
  • 分别用 Express 和 Fastify 平台启动项目,对比差异

第二课:Controller — 请求的入口

覆盖文档:Controllers 前置知识:第1课

课程内容

[基础] 路由与请求处理

  • @Controller('cats') 定义路由前缀
  • HTTP 方法装饰器:@Get(), @Post(), @Put(), @Delete(), @Patch(), @Options(), @Head(), @All()
  • 路由参数:@Param('id'), @Query('page'), @Body(), @Headers('authorization')
  • DTO(Data Transfer Object):用 class 定义请求体结构
  • 响应状态码:@HttpCode(204)
  • 响应头设置:@Header('Cache-Control', 'no-store')
  • 重定向:@Redirect('https://example.com', 301)

[中阶] 高级路由技巧

  • 路由通配符:@Get('abcd/*') 匹配任意路径
  • 子域名路由:@Controller({ host: ':account.example.com' })@HostParam('account')
  • 异步控制器:async/await 与 RxJS Observable 两种返回方式
  • 请求负载:@Query() 复杂查询参数解析(嵌套对象、数组)
  • Library-specific 模式:@Res({ passthrough: true }) 直接操作 Express/Fastify response 对象
  • 参数顺序:静态路由应声明在参数路由之前

[高阶] API 版本控制

  • 4 种版本策略:URI(/v1/cats)、Header、Media Type、Custom
  • app.enableVersioning({ type: VersioningType.URI })
  • 控制器级:@Controller({ version: '1' })
  • 路由级:@Version(['1', '2'])
  • VERSION_NEUTRAL 版本无关路由

[资深] 源码:路由注册机制

  • packages/common/decorators/http/request-mapping.decorator.ts@Get/@Post 如何通过 Reflect.defineMetadata 挂载路由信息
  • packages/core/router/router-explorer.ts:扫描 Controller 方法,提取路由元数据
  • packages/core/router/routes-resolver.ts:顶层路由解析协调器
  • Express adapter 如何将 NestJS 路由注册到底层 Express 路由表

[架构] RESTful API 设计

  • 资源命名规范:名词复数(/users),避免动词
  • HTTP 方法语义:GET 幂等、POST 创建、PUT 全量更新、PATCH 部分更新、DELETE 删除
  • 状态码选择策略:200/201/204/400/401/403/404/409/422/500
  • 全局路径前缀:app.setGlobalPrefix('api/v1'),排除健康检查路由
  • CRUD 代码生成:nest g resource cats 一键生成完整 CRUD 结构

课后实践

  • 实现一个完整的 CatsController:包含 CRUD 五个方法
  • 尝试用 @Query() 实现分页(page, limit)和过滤(breed, age)
  • nest g resource dogs 对比手写 vs 自动生成

第三课:Provider 与依赖注入 — 框架的灵魂

覆盖文档:Providers, Custom Providers, Async Providers 前置知识:第2课

课程内容

[基础] Service 与构造器注入

  • @Injectable() 装饰器:声明一个类可被 DI 容器管理
  • 构造器注入:constructor(private catsService: CatsService) {}
  • TypeScript 的 private 简写同时完成声明和赋值
  • Service 的职责:封装业务逻辑,Controller 只做路由分发
  • Provider 注册:@Module({ providers: [CatsService] })
  • @Optional() 可选依赖:未提供时不报错

[中阶] 四种 Provider 模式

  • useClass:默认模式,注册一个类
    { provide: CatsService, useClass: CatsService }  // 等价于直接写 CatsService
    
  • useValue:注入常量、配置对象、Mock 对象
    { provide: 'API_KEY', useValue: 'abc123' }
    
  • useFactory:工厂函数,可注入其他依赖、支持异步
    { provide: 'DB_CONNECTION', useFactory: async (config) => createConnection(config), inject: [ConfigService] }
    
  • useExisting:别名,两个 token 指向同一实例
  • 非类 token(string/Symbol)需要 @Inject('TOKEN') 注入
  • 属性注入:@Inject('HTTP_OPTIONS') private httpClient: T(不推荐,优先用构造器)

[高阶] 异步 Provider 与条件 Provider

  • 异步 Provider:useFactory 返回 Promise,启动时等待解析完成
  • 运行时条件选择:useClass 根据环境变量选择不同实现类
  • NEST_DEBUG=true 查看依赖解析日志
  • Provider 导出:exports: [CatsService] 使其对导入模块可用

[资深] 源码:DI 容器实现

  • packages/core/injector/container.tsNestContainer — 顶层容器,管理所有 Module
  • packages/core/injector/module.ts:每个 Module 内部维护 _providers_controllers_imports_exports 四个 Map
  • packages/core/injector/instance-wrapper.tsInstanceWrapper — 每个 provider 的元数据封装(实例、scope、依赖列表、是否已解析)
  • packages/core/injector/injector.tsresolveComponentInstance() — 依赖解析核心算法
  • Provider token 的解析顺序:类型 → 自定义 token → forwardRef

[架构] IoC/DI 设计模式

  • 控制反转(IoC)的本质:对象的创建和生命周期管理交给容器
  • 依赖倒置原则(DIP):高层模块不依赖低层模块,都依赖抽象
  • NestJS vs Spring:构造器注入 vs 字段注入的取舍
  • interface 在 NestJS 中的局限:TypeScript interface 编译后消失,需要用 class 或自定义 token
  • 何时使用 useFactory vs useClass:有条件逻辑或异步初始化时用 Factory

课后实践

  • 创建 CatsService 注入到 CatsController,实现内存数据的 CRUD
  • useValue 注入一个 mock 数据源,用 useFactory 注入一个异步初始化的数据库连接
  • NEST_DEBUG=true 观察依赖解析过程

第四课:Module 系统 — 应用的组织骨架

覆盖文档:Modules, Dynamic Modules, Lazy-loading Modules, CLI Workspaces, CLI Libraries 前置知识:第3课

课程内容

[基础] 模块基础

  • @Module() 四大属性:importscontrollersprovidersexports
  • 根模块 AppModule:整个应用的入口
  • 功能模块:按业务域组织代码(UsersModuleOrdersModule
  • nest g module cats 快速创建模块
  • 模块注册:在 AppModuleimports 中引入功能模块

[中阶] 模块间共享与全局模块

  • 共享模块:通过 exports 导出 provider,其他模块 imports 后即可使用
  • 模块单例性:同一模块在多处导入,provider 共享同一实例
  • 模块重导出:exports: [CommonModule] 让导入者间接获得 CommonModule 的能力
  • @Global() 全局模块:注册一次全应用可用(慎用,推荐显式 imports)
  • 模块内注入:模块类本身可以注入 provider(用于配置)

[高阶] 动态模块

  • 静态模块 vs 动态模块:固定配置 vs 运行时配置
  • forRoot() / forFeature() / register() 命名约定:
    • forRoot():全局配置一次(如数据库连接)
    • forFeature():功能模块按需注册(如实体/模型)
    • register():每个消费者独立配置
  • 动态模块返回 DynamicModule 对象:{ module, providers, exports }
  • ConfigurableModuleBuilder<T>:自动生成 register() / registerAsync() 的基类
    • MODULE_OPTIONS_TOKEN:自动生成的配置注入 token
    • .setClassMethodName('forRoot') 自定义方法名
    • .setExtras({ isGlobal: true }, ...) 添加额外选项
  • forRootAsync() 异步配置:useFactory / useClass / useExisting

[资深] 源码:模块扫描与编译

  • packages/core/scanner.tsDependenciesScanner
    • scanForModules():递归扫描 @Module()imports,构建模块树
    • scanModulesForDependencies():解析每个模块的 providers/controllers/exports
    • 处理 DynamicModule:调用 forRoot() 等静态方法获取运行时配置
  • packages/core/injector/compiler.ts:模块编译器,处理动态模块的合并
  • packages/common/module-utils/configurable-module.builder.tsConfigurableModuleBuilder 的实现
  • 懒加载:packages/core/injector/lazy-module-loader/lazy-module-loader.ts

[架构] 模块化架构设计

  • 模块边界设计:高内聚、低耦合
  • 分层架构模式:
    AppModule
    ├── CoreModule(全局单例:Logger、Config、Guards)
    ├── SharedModule(共享工具:HttpModule、CacheModule)
    ├── AuthModule(认证/授权)
    ├── UsersModule(用户域)
    ├── OrdersModule(订单域)
    └── PaymentsModule(支付域)
    
  • Monorepo 管理:nest g app admin-api 创建多应用,nest g library shared 创建共享库
  • 懒加载在 Serverless 场景的价值:减少冷启动时间
  • RouterModule:模块级路由前缀 RouterModule.register([{ path: 'admin', module: AdminModule }])

课后实践

  • 将第2、3课的代码重构为 CatsModule,确保 CatsService 被正确导出和共享
  • 创建一个 DatabaseModule.forRoot(config) 动态模块
  • ConfigurableModuleBuilder 重写上述动态模块,体会自动生成的便利

第五课:中间件与异常处理 — 请求管线第一层

覆盖文档:Middleware, Exception Filters, 内置异常类 前置知识:第4课

课程内容

[基础] 中间件基础

  • 中间件的职责:在路由处理器之前执行,可访问 req/res/next()
  • 类中间件:实现 NestMiddleware 接口,use(req, res, next) 方法
  • 函数中间件:简单场景下更简洁,无需 class
  • 注册中间件:模块实现 NestModule 接口,在 configure(consumer) 中使用 MiddlewareConsumer
  • forRoutes() 绑定路由:字符串、路由对象 { path, method }、Controller 类
  • exclude() 排除路由

[中阶] 中间件进阶

  • 多中间件:consumer.apply(cors(), helmet(), logger).forRoutes(CatsController)
  • 全局中间件:app.use(logger) — 无法使用 DI
  • 类中间件的 DI 能力:可通过构造器注入其他 provider
  • 通配符路由:forRoutes({ path: 'abcd/*splat', method: RequestMethod.ALL })
  • Express vs Fastify 中间件差异:Fastify 中间件接收原始 req/res

[基础] 异常基础

  • HttpException:手动抛出 throw new HttpException('Forbidden', HttpStatus.FORBIDDEN)
  • 内置异常类(24 种):BadRequestExceptionUnauthorizedExceptionNotFoundExceptionForbiddenExceptionConflictExceptionInternalServerErrorException
  • 异常响应格式:{ statusCode, message, error }
  • 自定义异常:继承 HttpException
  • cause 参数:传递底层错误用于日志记录

[中阶] 异常过滤器

  • @Catch(HttpException) + ExceptionFilter 接口:自定义异常响应格式
  • ArgumentsHosthost.switchToHttp() 获取 requestresponse
  • 绑定范围:方法级 @UseFilters()、控制器级、全局级 app.useGlobalFilters()
  • APP_FILTER token 注册全局 filter(支持 DI)
  • 全捕获过滤器:@Catch() 不传参数,捕获所有异常

[高阶] 平台无关异常处理

  • HttpAdapterHost:通过 HTTP 适配器抽象响应,不直接操作 Express/Fastify response
  • BaseExceptionFilter:继承内置 filter 并扩展
  • 异常日志策略:IntrinsicException 标记为"正常流程异常",默认不打日志

[资深] 源码:异常处理机制

  • packages/core/exceptions/exceptions-zone.tsExceptionsZone.run() 的全局 try-catch
  • packages/core/exceptions/base-exception-filter.ts:默认异常过滤器实现
  • packages/common/exceptions/http.exception.tsHttpException 基类
  • packages/common/exceptions/intrinsic.exception.ts:标记内置异常,影响日志行为
  • 异常过滤器的解析顺序:路由级 → 控制器级 → 全局级

[架构] 错误处理策略

  • 统一错误响应格式:{ code, message, timestamp, path }
  • 业务异常 vs 系统异常:业务异常(400-499)不该触发告警,系统异常(500)必须告警
  • 错误监控集成:Sentry(@sentry/nestjs
  • 敏感信息隔离:生产环境异常不暴露堆栈

课后实践

  • 实现一个 LoggerMiddleware,记录每个请求的 method、url、耗时
  • 实现一个 AllExceptionsFilter,统一返回 { code, message, timestamp, path } 格式
  • 将 filter 通过 APP_FILTER 注册为全局 filter,注入 HttpAdapterHost

第六课:Pipes — 数据的验证与转换

覆盖文档:Pipes, Validation(Techniques) 前置知识:第5课

课程内容

[基础] 内置管道

  • Pipe 的两大用途:验证(数据是否合法)和转换(数据类型转换)
  • 10 个内置管道:ParseIntPipeParseFloatPipeParseBoolPipeParseUUIDPipeParseEnumPipeParseArrayPipeParseDatePipeDefaultValuePipeParseFilePipeValidationPipe
  • 参数级绑定:@Param('id', ParseIntPipe) id: number
  • 错误响应示例:传入非数字时返回 400 Bad Request
  • 自定义错误码:new ParseIntPipe({ errorHttpStatusCode: HttpStatus.NOT_ACCEPTABLE })

[中阶] class-validator 验证

  • class-validator + class-transformer:声明式验证
  • DTO 装饰器:@IsString(), @IsInt(), @IsEmail(), @IsNotEmpty(), @Min(), @Max(), @IsOptional()
  • ValidationPipe 全局注册:app.useGlobalPipes(new ValidationPipe())
  • 关键选项:
    • whitelist: true:自动剥离未装饰的属性
    • forbidNonWhitelisted: true:未知属性直接报错
    • transform: true:自动转换为 DTO 实例 + 基本类型转换
    • disableErrorMessages: true:生产环境隐藏详细验证错误
  • 映射类型工具:PartialType()PickType()OmitType()IntersectionType()(来自 @nestjs/mapped-types

[中阶] Zod 验证

  • Zod schema 定义:z.object({ name: z.string(), age: z.number() }).required()
  • ZodValidationPipe:自定义管道调用 schema.parse(value)
  • @UsePipes(new ZodValidationPipe(schema)) 绑定到方法
  • Zod vs class-validator 对比:Zod 更函数式,class-validator 更声明式

[高阶] 自定义管道与转换管道

  • PipeTransform<T, R> 接口:transform(value: T, metadata: ArgumentMetadata): R
  • ArgumentMetadatatype(body/query/param/custom), metatype(类型类), data(装饰器参数名)
  • 转换管道用例:UserByIdPipe — 传入 id,返回完整 UserEntity
  • 管道执行顺序:全局 → 控制器 → 路由 → 参数级,参数从最后一个到第一个
  • APP_PIPE token 注册全局管道(支持 DI)

[资深] 源码:管道执行机制

  • packages/common/pipes/:10 个内置管道的实现
  • packages/common/pipes/validation.pipe.tsValidationPipe 内部调用 class-transformerplainToInstance()class-validatorvalidate()
  • packages/core/pipes/pipes-consumer.ts:管道的串联执行逻辑
  • 管道在请求管线中的位置:Guard 之后、Controller 之前

[架构] 验证策略选型

  • 单一验证层 vs 多层验证:API 边界必须验证,内部服务间信任
  • class-validator 适合:DTO 驱动、装饰器风格团队
  • Zod 适合:函数式风格、前后端共享 schema
  • 验证与业务规则分离:Pipe 做格式验证,Guard/Service 做业务规则校验
  • 文件验证:ParseFilePipe + MaxFileSizeValidator + FileTypeValidator

课后实践

  • CreateCatDto 添加 class-validator 装饰器,全局启用 ValidationPipe({ whitelist: true, transform: true })
  • PartialType(CreateCatDto) 创建 UpdateCatDto
  • 实现一个 CatByIdPipe:传入 id,从 CatsService 中查找并返回 Cat 实体

第七课:Guards 与 Interceptors — 权限控制与 AOP

覆盖文档:Guards, Interceptors, Execution Context 前置知识:第6课

课程内容

[基础] Guards 守卫

  • Guard 的职责:决定请求是否被允许继续处理(authorization)
  • CanActivate 接口:canActivate(context: ExecutionContext): boolean | Promise<boolean>
  • 返回 true 放行,返回 false 自动抛出 ForbiddenException
  • 绑定方式:@UseGuards(AuthGuard) — 方法级、控制器级
  • 全局绑定:app.useGlobalGuards()APP_GUARD token

[中阶] 角色守卫实战

  • Reflector.createDecorator<string[]>() 创建 @Roles(['admin']) 装饰器
  • RolesGuard:通过 Reflector.get() 读取当前路由的角色元数据
  • ExecutionContext:继承 ArgumentsHost,增加 getHandler()(当前方法)和 getClass()(控制器类)
  • Guard vs Middleware:Guard 知道下一步要执行什么(有 ExecutionContext),Middleware 不知道
  • Guard 执行顺序:全局 → 控制器 → 路由

[基础] Interceptors 拦截器

  • 拦截器的能力(AOP):
    1. 在方法执行前后绑定逻辑
    2. 转换返回结果
    3. 转换抛出的异常
    4. 扩展基本方法行为
    5. 完全覆盖方法(如缓存)
  • NestInterceptor 接口:intercept(context: ExecutionContext, next: CallHandler): Observable<any>
  • CallHandler.handle():调用路由处理器,返回 RxJS Observable

[中阶] 拦截器实战

  • 日志拦截器tap() 操作符记录请求前后的时间差
  • 响应映射map(data => ({ data })) 统一包装响应格式
  • 异常映射catchError() 转换异常类型
  • 超时控制timeout(5000) + catchError 处理 TimeoutError
  • 缓存拦截器of([]) 直接返回缓存值,跳过 handler
  • 绑定方式:@UseInterceptors() — 方法级、控制器级、全局级 / APP_INTERCEPTOR
  • 拦截器执行顺序:入方向 全局→控制器→路由,出方向 路由→控制器→全局(反序)

[高阶] ExecutionContext 与 Reflector 深入

  • ArgumentsHostswitchToHttp()switchToRpc()switchToWs() — 跨平台上下文切换
  • ExecutionContextgetHandler() 获取当前方法引用,getClass() 获取控制器类
  • Reflector 三种读取方式:
    • .get(decorator, target):从单个目标读取
    • .getAllAndOverride(key, [handler, class]):方法级覆盖类级
    • .getAllAndMerge(key, [handler, class]):合并方法级和类级

[资深] 源码:管线组装

  • packages/core/router/router-execution-context.ts:核心文件,组装 Guard → Interceptor → Pipe → Handler 管线
  • packages/core/guards/guards-consumer.ts:Guard 链的执行
  • packages/core/interceptors/interceptors-consumer.ts:Interceptor 链的执行
  • Guard 如何获取 ExecutionContext:框架在调用 canActivate 时注入

[架构] 横切关注点设计

  • Guard 做权限,Interceptor 做日志/缓存/转换 — 职责分离
  • 全局 vs 模块级增强器:APP_GUARD / APP_INTERCEPTOR 支持 DI,useGlobalXxx 不支持
  • 跨上下文统一(HTTP/WS/RPC/GraphQL):同一套 Guard/Interceptor 可复用
  • 性能考量:过多 Interceptor 链增加请求延迟

课后实践

  • 实现 JWT AuthGuard:从 Authorization header 提取 token 并验证
  • 实现 @Roles(['admin']) 装饰器 + RolesGuard:基于角色的路由保护
  • 实现 TransformInterceptor:统一响应为 { data, timestamp } 格式
  • 实现 TimeoutInterceptor:5 秒超时自动返回 408

第八课:自定义装饰器与元数据编程

覆盖文档:Custom Decorators, Custom Providers(进阶部分), Discovery Service 前置知识:第7课

课程内容

[基础] 自定义参数装饰器

  • createParamDecorator((data, ctx: ExecutionContext) => ...)
  • 示例:@User() 从请求中提取用户信息
  • 传递数据参数:@User('email') 提取用户特定属性
  • 自定义装饰器与 Pipe 配合:@User(new ValidationPipe({ validateCustomDecorators: true }))

[中阶] 装饰器组合

  • applyDecorators(...decorators):将多个装饰器合并为一个
  • 示例:@Auth('admin') = @SetMetadata('roles', ['admin']) + @UseGuards(AuthGuard, RolesGuard) + @ApiBearerAuth()
  • @SetMetadata(key, value):低层级元数据设置
  • 类装饰器 vs 方法装饰器 vs 参数装饰器的区别

[高阶] Discovery Service 运行时内省

  • DiscoveryModule + DiscoveryService(from @nestjs/core
  • .getProviders():获取所有已注册 provider 及其元数据
  • .getControllers():获取所有 controller
  • 按装饰器过滤:基于自定义装饰器找出特定 provider
  • 应用场景:插件自动发现、自动注册事件处理器、运行时生成路由表

[资深] 源码:装饰器与 Reflect Metadata

  • TypeScript emitDecoratorMetadata 编译选项的作用
  • Reflect.defineMetadata / Reflect.getMetadata / Reflect.getOwnMetadata
  • packages/common/constants.ts:所有内置元数据 key(CONTROLLER_WATERMARKINJECTABLE_WATERMARKMODULE_METADATA 等)
  • 装饰器如何被 Scanner 和 Router 消费:运行时读取元数据 → 构建依赖图/路由表
  • packages/core/discovery/discovery-service.ts:DiscoveryService 的实现

[架构] 元数据驱动架构

  • 声明式编程的优势:配置即代码,减少样板
  • 装饰器模式在企业级框架中的应用:Spring Annotations vs NestJS Decorators vs Python Decorators
  • 自定义装饰器的设计原则:单一职责,可组合
  • 利用 Discovery Service 构建插件系统

课后实践

  • 实现 @Public() 装饰器标记无需认证的路由,修改 AuthGuard 通过 Reflector 跳过公开路由
  • 实现 @Auth('admin', 'editor') 组合装饰器
  • 使用 DiscoveryService 在应用启动时列出所有带 @Cacheable() 装饰器的方法

第九课:注入作用域与应用生命周期

覆盖文档:Injection Scopes, Circular Dependency, Module Reference, Lifecycle Events, Platform Agnosticism 前置知识:第8课

课程内容

[基础] 三种注入作用域

  • Scope.DEFAULT(Singleton):默认,全应用共享一个实例
  • Scope.REQUEST:每个请求创建新实例,请求结束后销毁
  • Scope.TRANSIENT:每次注入创建新实例
  • 设置方式:@Injectable({ scope: Scope.REQUEST })
  • REQUEST token:在 Request-scoped provider 中注入原始请求对象

[中阶] Scope 冒泡与生命周期

  • Scope 冒泡规则:如果 Service 是 Request-scoped,依赖它的 Controller 也变成 Request-scoped
  • 性能影响:Request-scoped 每次请求都创建/销毁实例链,影响性能
  • INQUIRER token:Transient provider 中获取"谁注入了我"
  • 生命周期钩子(按执行顺序):
    1. onModuleInit():模块依赖解析完成
    2. onApplicationBootstrap():所有模块初始化完成,开始监听前
    3. onModuleDestroy():收到终止信号
    4. beforeApplicationShutdown(signal):所有 onModuleDestroy 完成后
    5. onApplicationShutdown(signal):连接关闭后
  • app.enableShutdownHooks():必须显式启用终止钩子

[高阶] 循环依赖与 ModuleRef

  • 循环依赖解决:forwardRef(() => CatService) — Provider 间和 Module 间都适用
  • 避免 barrel file(index.ts)导致的虚假循环依赖
  • ModuleRef:运行时动态访问 DI 容器
    • .get(token):获取 Singleton 实例
    • .resolve(token, contextId):获取 Scoped 实例
    • .create(Class):在容器外动态实例化一个类
  • ContextIdFactory:创建/获取上下文 ID
  • 持久提供者(Durable Providers):多租户场景,按租户缓存 DI 子树

[资深] 源码:作用域与生命周期实现

  • packages/core/injector/instance-wrapper.ts:Scope 属性如何影响实例创建
  • packages/core/injector/injector.ts:Singleton vs Request vs Transient 的解析路径分支
  • packages/core/nest-application-context.ts:生命周期钩子的执行引擎
  • packages/core/hooks/:钩子的调用逻辑
  • packages/core/injector/module-ref.ts:ModuleRef 的实现

[架构] 多租户与请求隔离架构

  • Singleton 为主、Request-scoped 为辅的原则
  • 替代 Request-scoped 的方案:AsyncLocalStoragenestjs-cls 包),无 scope 冒泡开销
  • 持久提供者在多租户 SaaS 中的应用
  • 优雅关闭策略:enableShutdownHooks + beforeApplicationShutdown 中等待进行中的请求完成
  • 平台无关性:同一套 Guard/Pipe/Interceptor 在 HTTP/WS/RPC/GraphQL 中复用

课后实践

  • 创建一个 Request-scoped 的 RequestLoggerService,注入 REQUEST 获取请求信息
  • 实现 onModuleInit 在模块启动时打印配置信息
  • ModuleRef.resolve() 验证 Transient provider 每次返回不同实例

第十课:数据持久化 — 数据库集成全方案

覆盖文档:Database, MongoDB, Serialization, Recipes(TypeORM/Mongoose/Prisma/MikroORM/Sequelize) 前置知识:第9课 文档页数:7 页 | 核心主题:5

课程内容

[基础] TypeORM 集成

  • 安装:@nestjs/typeorm + typeorm + 数据库驱动(mysql2/pg
  • TypeOrmModule.forRoot({ type, host, port, username, password, database, entities, synchronize })
  • 实体定义:@Entity() + @Column() + @PrimaryGeneratedColumn()
  • TypeOrmModule.forFeature([CatEntity]):按模块注册实体
  • @InjectRepository(CatEntity):注入 Repository<CatEntity>
  • 基本 CRUD:.find(), .findOneBy(), .save(), .remove()
  • autoLoadEntities: true:自动发现 forFeature 注册的实体

[中阶] Mongoose 与 Prisma

  • Mongoose 集成
    • MongooseModule.forRoot('mongodb://...')
    • Schema 定义:@Schema() + @Prop() 装饰器
    • MongooseModule.forFeature([{ name: Cat.name, schema: CatSchema }])
    • @InjectModel(Cat.name) 注入 Model<Cat>
    • Hook、Plugin、Discriminator(Schema 继承)
  • Prisma 集成
    • Schema 文件定义模型,npx prisma generate 生成类型安全客户端
    • PrismaService extends PrismaClient,直接注入使用
    • 类型安全的 CRUD:prisma.cat.findMany(), .create(), .update()

[高阶] 数据层进阶

  • 多数据库连接:TypeOrmModule.forRoot({ name: 'secondary', ... })
  • 异步配置:forRootAsync({ useFactory, inject: [ConfigService] })
  • 事务处理:TypeORM QueryRunner,Sequelize sequelize.transaction()
  • 序列化控制(class-transformer):
    • @Exclude() 隐藏密码等敏感字段
    • @Expose() 计算属性
    • @Transform() 自定义转换
    • ClassSerializerInterceptor 全局启用
  • MikroORM:Data Mapper + Unit of Work 模式,@CreateRequestContext() 自动请求上下文
  • synchronize: true 仅限开发环境,生产必须用 migration

[资深] 源码与 Provider 模式

  • @nestjs/typeormforRoot/forFeature 是动态模块的经典实现
  • getRepositoryToken(Entity) 用于测试时 mock Repository
  • 自定义 Repository 实现
  • TypeORM EntitySubscriber:实体事件监听

[架构] 数据层架构选型

  • ORM 对比:

    特性TypeORMPrismaMongooseMikroORMSequelize
    模式Active Record + Data Mapper声明式 SchemaSchema + ModelData Mapper + UoWActive Record
    类型安全
    迁移内置内置(优秀)内置内置
    适用SQL 全场景新项目首选MongoDB复杂域模型遗留项目
  • Repository 模式 vs Active Record:NestJS 推荐 Repository

  • 读写分离、连接池配置

  • 测试策略:mock Repository vs 真实数据库(内存数据库/Testcontainers)

课后实践

  • 选择一种 ORM,为 CatsModule 添加真实数据库持久化
  • 实现 @Exclude() 隐藏 password 字段,ClassSerializerInterceptor 全局启用
  • 编写单元测试,mock Repository<CatEntity>

第十一课:认证与授权 — 身份验证体系

覆盖文档:Authentication, Authorization, Passport(Recipe) 前置知识:第7课(Guards)、第10课 文档页数:4 页 | 核心主题:5

课程内容

[基础] JWT 认证

  • 认证流程:用户名/密码登录 → 服务端验证 → 签发 JWT → 客户端携带 Bearer Token → 服务端验证 Token
  • @nestjs/jwtJwtModule.register({ global: true, secret, signOptions: { expiresIn } })
  • AuthService.signIn():验证凭据 + jwtService.signAsync(payload)
  • AuthGuard:从 Authorization: Bearer xxx 提取 token,jwtService.verifyAsync() 验证
  • 全局启用:{ provide: APP_GUARD, useClass: AuthGuard }
  • @Public() 装饰器:标记公开路由跳过认证

[中阶] Passport 集成与密码安全

  • Passport 策略模式:PassportStrategy(Strategy) 继承 + validate() 方法
  • LocalStrategy:用户名/密码本地验证
  • JwtStrategy:JWT token 自动解码和验证
  • AuthGuard('local')AuthGuard('jwt') 的使用
  • 密码哈希:bcrypt.hash(password, salt)bcrypt.compare(plain, hashed)
  • 不要明文存储密码,不要在日志中打印密码

[中阶] 授权(RBAC)

  • 角色枚举:enum Role { User = 'user', Admin = 'admin' }
  • @Roles(Role.Admin) + RolesGuard + Reflector
  • 权限合并策略:getAllAndOverride(方法级覆盖类级) vs getAllAndMerge(合并)

[高阶] CASL 细粒度权限

  • CASL(Attribute-based Access Control):CaslAbilityFactory 定义能力
  • PoliciesGuard + @CheckPolicies(handler) 装饰器
  • Policy Handler:回调函数式或类实现 IPolicyHandler 接口
  • 字段级权限控制

[资深] 认证源码解析

  • AuthGuard 如何通过 Reflector 读取 @Public() 元数据跳过认证
  • @nestjs/jwtJwtModuleConfigurableModuleBuilder 的实际应用
  • Passport 策略的适配器模式

[架构] 认证架构设计

  • 认证 vs 授权:认证回答"你是谁",授权回答"你能做什么"
  • Token 刷新策略:Access Token(短期) + Refresh Token(长期)
  • 零信任架构:每个微服务独立验证 Token
  • 敏感操作二次验证

课后实践

  • 实现完整的 JWT 认证流程:注册 → 登录 → 受保护路由
  • 添加 @Roles() + RolesGuard 实现基于角色的访问控制
  • 用 Passport 实现 Local + JWT 双策略认证

第十二课:安全加固 — 防御纵深

覆盖文档:Encryption and Hashing, Helmet, CORS, CSRF Protection, Rate Limiting 前置知识:第11课 文档页数:5 页 | 核心主题:5

课程内容

[基础] Helmet 与 CORS

  • Helmetapp.use(helmet()) — 设置 15+ 安全响应头(CSP、X-Frame-Options 等)
  • Helmet 必须在其他中间件之前注册
  • Fastify 使用 @fastify/helmetapp.register(helmet)
  • CORSapp.enableCors({ origin, methods, credentials })NestFactory.create(AppModule, { cors: true })
  • CORS 配置选项:origin(白名单)、methodsallowedHeaderscredentials

[中阶] CSRF 防护与限流

  • CSRFcsrf-csrf 包实现双重提交 Cookie 模式
    • 需要先注册 cookie-parser 或 session 中间件
    • doubleCsrfProtection 作为全局中间件
    • Fastify:使用 @fastify/csrf-protection
  • 限流@nestjs/throttler
    • ThrottlerModule.forRoot([{ name: 'short', ttl: 1000, limit: 3 }, { name: 'long', ttl: 60000, limit: 100 }])
    • { provide: APP_GUARD, useClass: ThrottlerGuard }
    • @SkipThrottle() 跳过限流,@Throttle({ short: { ttl, limit } }) 自定义限流
    • 时间助手:seconds(1), minutes(1), hours(1)
    • 多限流策略同时生效(short/medium/long)
    • 自定义存储后端(Redis)用于分布式限流

[高阶] 加密与哈希

  • 加密 vs 哈希:加密可逆(AES),哈希不可逆(bcrypt/argon2)
  • 对称加密:AES-256-CTR,crypto.createCipheriv/createDecipheriv
  • 密钥派生:crypto.scrypt(password, salt, keylen)
  • 随机 IV:crypto.randomBytes(16)
  • 密码哈希:bcrypt.hash(password, saltRounds)bcrypt.compare(plain, hashed)

[资深] Node.js crypto 模块深入

  • crypto.scrypt vs crypto.pbkdf2:两种密钥派生算法对比
  • 安全随机数生成:crypto.randomBytes vs Math.random
  • JWT secret 安全性:长度、复杂度、轮换策略

[架构] 安全架构设计

  • 安全防护清单:HTTPS + Helmet + CORS + CSRF + Rate Limiting + 输入验证
  • 分层防御策略:网络层(WAF/CDN)→ 传输层(TLS)→ 应用层(NestJS Guards)→ 数据层(加密存储)
  • 安全审计与合规要求
  • 定期依赖漏洞扫描:npm audit

课后实践

  • 为应用配置 Helmet + CORS + ThrottlerGuard 完整安全组合
  • 实现密码哈希注册/登录流程(bcrypt)
  • 测试限流效果:用快速请求触发 429 Too Many Requests

第十三课:配置、日志与事件 — 应用基础设施

覆盖文档:Configuration, Logger, Events, Cookies, Session 前置知识:第9课(Dynamic Modules) 文档页数:5 页 | 核心主题:5

课程内容

[基础] 配置管理

  • @nestjs/config:基于 dotenvConfigModule.forRoot({ isGlobal: true })
  • ConfigService.get<string>('DATABASE_HOST')
  • 类型安全:get('port', { infer: true })
  • .env 文件 + 环境变量优先级:运行时环境变量 > .env 文件

[中阶] 配置进阶

  • 命名空间:registerAs('database', () => ({ host, port }))
  • ConfigModule.forFeature(databaseConfig):功能模块局部配置
  • Joi Schema 验证:validationSchema: Joi.object({ PORT: Joi.number().default(3000) })
  • 自定义 YAML 配置文件:js-yaml 加载
  • expandVariables: true:支持环境变量插值 ${DB_HOST}
  • ConditionalModule.registerWhen():基于环境变量条件加载模块

[基础] 日志系统

  • 内置 Logger 类:private readonly logger = new Logger(MyService.name)
  • 日志级别:log, error, warn, debug, verbose, fatal(级联)
  • 禁用/过滤日志:NestFactory.create(AppModule, { logger: ['error', 'warn'] })
  • ConsoleLogger JSON 输出:new ConsoleLogger({ json: true }) — 适合日志聚合

[中阶] 自定义 Logger 与事件驱动

  • 自定义 Logger:实现 LoggerService 接口或继承 ConsoleLogger
  • DI 注入自定义 Logger:app.useLogger(app.get(MyLogger)) + bufferLogs: true
  • Transient scope 实现每个 Service 独立 Logger 实例
  • 事件驱动@nestjs/event-emitter(wraps eventemitter2
    • EventEmitterModule.forRoot()
    • 发射:eventEmitter.emit('order.created', payload)
    • 监听:@OnEvent('order.created'),通配符:@OnEvent('order.*')

[中阶] Cookie 与 Session

  • Cookiecookie-parser(Express)/ @fastify/cookie(Fastify),自定义 @Cookies() 装饰器
  • Sessionexpress-session(Express)/ @fastify/secure-session(Fastify)
    • @Session() 装饰器访问会话
    • 生产环境必须使用外部 session store(Redis)

[资深] 源码:ConfigModule 实现

  • @nestjs/configConfigurableModuleBuilder 的典型应用
  • registerAs() 的实现:命名空间 token 生成
  • ConfigService.get() 的类型推断机制

[架构] 配置与日志架构

  • 12-Factor App 原则:环境变量优先,不硬编码
  • 结构化 JSON 日志 → ELK/Datadog 集中收集
  • 关联 ID(Correlation ID):贯穿请求全链路的唯一标识
  • 日志分级策略:开发用 debug/verbose,生产只用 log/warn/error

课后实践

  • @nestjs/config 将数据库配置从硬编码改为 .env 文件驱动
  • 实现自定义 FileLogger(继承 ConsoleLogger,写入文件)
  • 用 EventEmitter 实现"用户注册后发送欢迎邮件"的解耦场景

第十四课:异步处理 — 缓存、队列与定时任务

覆盖文档:Caching, Queues, Task Scheduling 前置知识:第13课 文档页数:3 页 | 核心主题:3(每个主题深度讲解)

课程内容

[基础] 缓存

  • @nestjs/cache-manager(基于 cache-manager + Keyv)
  • CacheModule.register({ ttl: 5000, isGlobal: true })
  • 手动操作:@Inject(CACHE_MANAGER) cacheManager: Cache.get() / .set() / .del() / .clear()
  • CacheInterceptor 自动缓存 GET 请求
  • @CacheKey('custom_key')@CacheTTL(10000) 覆盖默认值

[中阶] Redis 缓存后端

  • Redis 后端:@keyv/redis
  • 多级缓存:内存 + Redis 组合
  • 自定义 CacheInterceptor:覆盖 trackBy() 实现自定义缓存键
  • 异步配置:CacheModule.registerAsync({ useFactory, inject: [ConfigService] })

[基础] 定时任务

  • @nestjs/scheduleScheduleModule.forRoot()
  • @Cron('45 * * * * *') / @Cron(CronExpression.EVERY_10_SECONDS)
  • @Interval(10000) 重复执行 / @Timeout(5000) 延迟一次执行
  • Cron 选项:name, timeZone, waitForCompletion, disabled

[中阶] 动态调度管理

  • SchedulerRegistrygetCronJob(name), addCronJob(), deleteCronJob()
  • 动态创建/停止/重启定时任务
  • setTime() 运行时修改调度时间
  • 异常自动捕获并记录日志

[中阶] 消息队列

  • @nestjs/bullmq + Redis
  • BullModule.forRoot({ connection: { host, port } })
  • BullModule.registerQueue({ name: 'audio' })
  • Producer:@InjectQueue('audio'), queue.add('transcode', data, { priority, delay, attempts })
  • Consumer:@Processor('audio') + WorkerHost,实现 process(job) 方法
  • Job 选项:priority, delay, attempts, backoff, repeat, removeOnComplete

[高阶] 队列进阶

  • Worker 事件:@OnWorkerEvent('active'|'completed'|'failed')
  • Queue 事件:@QueueEventsListener('audio') + @OnQueueEvent('waiting')
  • Flow Producer:父子 Job 关系(BullModule.registerFlowProducer
  • Request-scoped Consumer:scope: Scope.REQUEST
  • 独立进程执行:processors 选项实现沙箱化 Job 处理

[资深] 源码:调度与队列机制

  • @nestjs/schedule 内部使用 cron
  • @Cron 装饰器通过 DiscoveryService 自动发现并注册
  • BullMQ 的 Redis 数据结构:Sorted Set 实现延迟队列

[架构] 异步处理架构

  • 同步 vs 异步处理:用户请求中不应执行耗时任务
  • 缓存策略:Cache-Aside(旁路缓存)vs Read-Through vs Write-Behind
  • 队列选型:BullMQ(Redis,中等规模)vs RabbitMQ(可靠投递)vs Kafka(大规模流处理)
  • 幂等性设计:队列消费者必须处理重复消息

课后实践

  • CacheInterceptor 缓存 GET /cats 接口,Redis 作后端
  • 实现 @Cron 定时任务定期清理过期数据
  • 用 BullMQ 实现图片异步转码:API 接收上传 → 入队 → Worker 处理 → 通知完成

第十五课:文件、HTTP 与其他实用技术

覆盖文档:File Upload, Streaming Files, HTTP Module, Server-Sent Events, Compression, MVC, Serve Static, Versioning(回顾) 前置知识:第13课 文档页数:7 页 | 核心主题:6

课程内容

[基础] 文件上传

  • Multer(Express only,Fastify 不兼容)
  • 单文件:@UseInterceptors(FileInterceptor('file')) + @UploadedFile()
  • 多文件:FilesInterceptor('files', 10) + @UploadedFiles()
  • 多字段:FileFieldsInterceptor([{ name: 'avatar', maxCount: 1 }, { name: 'photos', maxCount: 5 }])
  • 验证:ParseFilePipe + MaxFileSizeValidator + FileTypeValidator(基于 magic bytes)
  • ParseFilePipeBuilder 流式构建验证规则
  • MulterModule.register({ dest: './uploads' }) 配置默认上传目录

[中阶] 流式传输与 HTTP 客户端

  • 流式文件传输new StreamableFile(readStream) — 跨平台文件下载
    • 构造函数接受 BufferStream
    • 选项:type(Content-Type), disposition(Content-Disposition), length
  • HTTP 客户端@nestjs/axios(wraps Axios)
    • HttpModule.register({ timeout: 5000, maxRedirects: 5 })
    • httpService.get<T>(url) 返回 Observable<AxiosResponse<T>>
    • 转 Promise:firstValueFrom(httpService.get(url))
    • 直接 Axios:httpService.axiosRef 获取原生实例

[中阶] SSE 与其他技术

  • Server-Sent Events@Sse('events') + 返回 Observable<MessageEvent>
    • MessageEventdata(必须), id, type, retry
    • 客户端:new EventSource('/sse')
  • 压缩compression(Express)/ @fastify/compress(Fastify),生产推荐 Nginx 层处理
  • MVC 渲染app.setViewEngine('hbs') + @Render('index')
    • Express:useStaticAssets() + setBaseViewsDir() + setViewEngine()
    • Fastify:@fastify/view + @fastify/static
  • 静态文件@nestjs/serve-staticServeStaticModule.forRoot({ rootPath })

[高阶] 跨技术的通用配置模式

  • forRoot() / forRootAsync() / forFeature() 是所有技术模块的统一配置模式
  • registerAsync({ useFactory, inject: [ConfigService] }) 实现配置驱动
  • 全局 vs 模块级注册的权衡
  • extraProviders 选项向模块注入额外依赖

[资深] 源码:StreamableFile 实现

  • packages/common/file-stream/streamable-file.ts:跨平台文件流抽象
  • Express 和 Fastify 对文件流的不同处理方式

[架构] 文件与通信策略

  • 大文件上传:分片上传 + 断点续传 + 对象存储(S3/OSS)
  • SSE vs WebSocket vs 轮询:SSE 适合单向服务器推送,WebSocket 适合双向通信
  • 文件存储策略:本地磁盘(开发)→ 对象存储(生产)

课后实践

  • 实现文件上传接口,限制最大 5MB + 只允许图片类型
  • 实现文件下载接口,使用 StreamableFile 流式返回
  • 实现一个 SSE 端点,每秒推送服务器时间

第十六课:WebSocket 实时通信

覆盖文档:WebSockets(Gateways, Exception Filters, Pipes, Guards, Interceptors, Adapters) 前置知识:第9课 文档页数:6 页 | 核心主题:4

课程内容

[基础] WebSocket 网关

  • @WebSocketGateway() 装饰器:默认与 HTTP 共享端口
  • @SubscribeMessage('events') 订阅消息
  • @MessageBody() 提取消息数据,@ConnectedSocket() 获取客户端引用
  • @WebSocketServer() 获取底层 Server 实例
  • 响应方式:返回值自动发送、client.emit() 主动推送、Observable 多次发送
  • 生命周期钩子:OnGatewayInitOnGatewayConnectionOnGatewayDisconnect
  • 注册:将 Gateway 加入 Module 的 providers 数组

[中阶] Socket.IO 与 ws 平台

  • Socket.IO(默认):功能丰富 — 房间、命名空间、自动重连、二进制支持
  • ws:轻量高性能,原生浏览器 WebSocket 兼容
  • 适配器切换:app.useWebSocketAdapter(new WsAdapter(app))
  • 命名空间:@WebSocketGateway({ namespace: 'chat' })
  • 端口配置:@WebSocketGateway(3001) 监听独立端口
  • Socket 选项透传:@WebSocketGateway({ cors: { origin: '*' } })

[中阶] WebSocket 增强器

  • Guard/Pipe/Interceptor/Filter 用法与 HTTP 完全一致
  • 关键差异:异常改用 WsException(而非 HttpException
  • WsException 自动发送 'exception' 事件给客户端
  • BaseWsExceptionFilter 继承并自定义异常处理
  • ValidationPipe 需要自定义 exceptionFactory 抛出 WsException

[高阶] 适配器与多实例部署

  • WebSocketAdapter 接口:create(), bindClientConnect(), bindMessageHandlers(), close()
  • 继承 IoAdapter 扩展功能
  • Redis 适配器:@socket.io/redis-adapter — 多实例部署时通过 Redis 同步消息
  • 负载均衡注意:Socket.IO 需要 sticky sessions 或禁用 polling

[资深] 源码:WebSocket 模块

  • packages/websockets/:WebSocket 模块核心
  • @SubscribeMessage 装饰器如何注册消息处理器
  • Gateway 的实例化和连接管理
  • WebSocketAdapter 的抽象层设计

[架构] 实时通信架构

  • WebSocket 应用场景:聊天、实时通知、协作编辑、游戏、仪表盘
  • 连接管理:心跳检测、断线重连、连接池大小
  • 水平扩展方案:Redis Pub/Sub 广播、专用 WebSocket 集群
  • WebSocket vs SSE vs Long Polling 选型

课后实践

  • 实现聊天室网关:@SubscribeMessage('message') 广播消息给所有连接
  • 添加 AuthGuard 保护 WebSocket 连接(验证 handshake 中的 token)
  • 实现 WsExceptionFilter 自定义错误格式

第十七课:微服务架构

覆盖文档:Microservices(Overview, Redis, MQTT, NATS, RabbitMQ, Kafka, gRPC, Custom Transport, Exception Filters, Pipes, Guards, Interceptors), Hybrid Application(FAQ) 前置知识:第16课 文档页数:13 页 | 核心主题:5

课程内容

[基础] 微服务入门

  • 微服务 vs HTTP:不走 HTTP 协议,使用消息传递
  • 两种消息模式:
    • 请求-响应@MessagePattern('sum')):client.send() 返回 Observable,等待响应
    • 事件@EventPattern('user_created')):client.emit() 发射即忘
  • TCP 传输(最简入门):
    • Server:NestFactory.createMicroservice(AppModule, { transport: Transport.TCP, options: { port: 3001 } })
    • Client:ClientsModule.register([{ name: 'MATH_SERVICE', transport: Transport.TCP }])
    • @Inject('MATH_SERVICE') client: ClientProxy
  • @Payload()@Ctx() 装饰器获取消息数据和上下文
  • ClientProxystatus 流和 connect() 方法

[中阶] 7 种传输层

传输层特点适用场景
TCP内置最简单,无外部依赖本地/内网微服务通信
RedisioredisPub/Sub,轻量,消息不持久化简单事件分发
NATSnats高性能,分布式队列,queue 负载均衡高吞吐消息传递
MQTTmqttIoT 协议,3 级 QoS,Topic 通配符物联网设备通信
RabbitMQamqplib消息确认(ACK),持久化,交换机类型可靠消息传递
Kafkakafkajs流处理,分区,持久化,消费者组大规模数据流
gRPC@grpc/grpc-jsProtocol Buffers,强类型,流式调用高性能内部 RPC
  • 各传输层特有 Context:RedisContext.getChannel()KafkaContext.getTopic()RmqContext.getMessage()
  • Record Builder:NatsRecordBuilderMqttRecordBuilderRmqRecordBuilderKafkaRecordBuilder

[高阶] 混合应用与自定义传输

  • 混合应用:app.connectMicroservice<MicroserviceOptions>({...}) + app.startAllMicroservices()
    • 一个应用同时监听 HTTP + 微服务
    • inheritAppConfig: true:全局 Guard/Pipe/Interceptor 共享
  • 微服务增强器:Pipes/Guards/Interceptors/Filters 用法与 HTTP 一致,异常改用 RpcException
  • 自定义传输策略:
    • Server:继承 Server,实现 CustomTransportStrategylisten(), close()
    • Client:继承 ClientProxypublish(), dispatchEvent(), connect(), close()
  • gRPC 特性:.proto 文件定义服务,@GrpcMethod()@GrpcStreamMethod()@GrpcStreamCall()
  • Kafka 特性:消费者组、手动 offset 提交、心跳机制、KafkaRetriableException

[资深] 源码:微服务抽象

  • packages/microservices/server/server.ts:Server 基类,messageHandlers Map 存储消息处理器
  • packages/microservices/client/client-proxy.ts:ClientProxy 基类,send()emit() 的实现
  • packages/microservices/server/server-tcp.ts:TCP 传输的完整实现(最适合入门阅读)
  • ReadPacket<T> / WritePacket<T>:消息协议数据结构
  • 传输层的策略模式:所有传输共享同一套 @MessagePattern/@EventPattern 接口

[架构] 分布式系统设计

  • 微服务拆分原则:按业务域,每个服务有独立数据存储
  • 通信模式选择:同步 RPC(gRPC/TCP)vs 异步消息(Kafka/RabbitMQ/NATS)
  • 数据一致性:最终一致性 vs 强一致性,Saga 模式
  • 服务发现与负载均衡
  • 传输层选型决策树:
    • 需要强类型 + 高性能 → gRPC
    • 需要可靠投递 + 消息确认 → RabbitMQ
    • 需要大规模事件流 → Kafka
    • 简单事件广播 → Redis/NATS

课后实践

  • 创建两个微服务(TCP):计算服务 + API 网关,网关转发请求到计算服务
  • 将 TCP 传输切换为 Redis Pub/Sub,观察代码变化量(几乎为零)
  • 创建混合应用:同时监听 HTTP 3000 端口 + TCP 3001 端口

第十八课:GraphQL — 类型安全的 API

覆盖文档:GraphQL(Quick Start, Resolvers, Mutations, Subscriptions, Scalars, Directives, Interfaces, Unions/Enums, Field Middleware, Mapped Types, Plugins, Complexity, Extensions, CLI Plugin, Generating SDL, Sharing Models, Other Features, Federation) 前置知识:第9课 文档页数:18 页 | 核心主题:6

课程内容

[基础] GraphQL 入门

  • Code First vs Schema First:
    • Code First:TypeScript 类 + 装饰器 → 自动生成 SDL(推荐)
    • Schema First:先写 .graphql 文件 → GraphQLDefinitionsFactory 生成 TypeScript 类型
  • Apollo vs Mercurius:@nestjs/apollo(主流) vs @nestjs/mercurius(Fastify 原生)
  • 配置:GraphQLModule.forRoot<ApolloDriverConfig>(ApolloDriver, { autoSchemaFile: true })
  • 类型定义:@ObjectType() + @Field(() => Int) 定义 GraphQL 类型
  • 解析器:@Resolver(() => Cat) + @Query() + @Mutation() + @ResolveField()
  • @Args() 提取参数,@InputType() 定义输入类型

[中阶] 类型系统

  • 标量类型:内置 GraphQLISODateTime/GraphQLTimestamp@Scalar() 自定义(parseValue/serialize/parseLiteral)
  • 接口@InterfaceType() + resolveType 动态类型判断
  • 联合类型createUnionType({ name, types: () => [Cat, Dog] as const })
  • 枚举registerEnumType(Role, { name: 'Role' })
  • 映射类型PartialType(), PickType(), OmitType(), IntersectionType()

[中阶] 订阅与中间件

  • SubscriptionsPubSub + @Subscription() + asyncIterableIterator
    • 通过 graphql-ws 配置(Apollo 推荐)
    • filter 函数筛选推送目标
    • resolve 函数修改推送数据
    • 生产环境使用外部 PubSub(Redis)
  • 字段中间件@Field({ middleware: [loggerMiddleware] }) — 字段级前后逻辑
  • 指令@Directive('@upper') + mapSchema transformer + transformSchema 选项
  • GraphQL 中的 Guard/Interceptor/Filter:GqlExecutionContext.create(context) 获取 GraphQL 上下文

[高阶] 高级特性

  • 查询复杂度限制graphql-query-complexity + ComplexityPlugin 防止恶意深查询
  • Extensions@Extensions({ role: Role.ADMIN }) 字段级元数据 + 字段中间件权限检查
  • Plugins@Plugin() 实现 ApolloServerPlugin — 请求生命周期钩子
  • CLI Pluginnest-cli.json 配置后编译时自动添加 @Field(),减少 80% 样板代码
  • 前后端模型共享:webpack alias 指向 @nestjs/graphql/dist/extra/graphql-model-shim
  • SDL 生成GraphQLSchemaBuilderModule + GraphQLSchemaFactory 离线生成 schema

[高阶] Federation 微服务联邦

  • Apollo Federation:拆分为多个 Subgraph 服务 + Gateway 聚合
  • ApolloFederationDriver:Subgraph 配置
  • @Directive('@key(fields: "id")') 标记实体主键
  • @ResolveReference() 实现跨服务实体解析
  • Gateway:ApolloGatewayDriver + IntrospectAndCompose 服务发现
  • 限制:Federation 不支持 Subscriptions

[资深] 源码:GraphQL 模块

  • @nestjs/graphqlforRoot() 动态模块实现
  • Resolver 是如何被 DiscoveryService 发现并注册的
  • GraphQLSchemaHost 提供运行时 schema 访问

[架构] GraphQL 架构策略

  • REST vs GraphQL:REST 适合简单 CRUD + 开放 API,GraphQL 适合前端灵活查询 + BFF 层
  • Schema 设计原则:以客户端需求为导向,避免过度暴露内部数据模型
  • N+1 问题:DataLoader 批量加载
  • Federation vs Schema Stitching:Federation 是官方推荐的微服务方案

课后实践

  • 为 CatsModule 实现 GraphQL Code First 版本(Query + Mutation)
  • 实现 Subscription:新增 Cat 时实时推送
  • 添加 ComplexityPlugin 限制查询深度

第十九课:API 文档与测试 — 质量保障

覆盖文档:OpenAPI(8页全部), Testing(Fundamentals), Recipes(REPL, CRUD Generator, Suites, Compodoc) 前置知识:第9课 文档页数:10 页 | 核心主题:5

课程内容

[基础] OpenAPI / Swagger

  • @nestjs/swagger:基于装饰器自动生成 API 文档
  • DocumentBuilder.setTitle(), .setDescription(), .setVersion(), .addBearerAuth(), .build()
  • SwaggerModule.createDocument(app, config) + SwaggerModule.setup('api', app, document)
  • @ApiProperty() 标注 DTO 属性
  • @ApiTags('cats') 标注控制器分组
  • 25+ 响应装饰器:@ApiOkResponse(), @ApiCreatedResponse(), @ApiForbiddenResponse()
  • 自动生成 JSON/YAML 端点:/api-json, /api-yaml

[中阶] OpenAPI 进阶

  • CLI Plugin 自动推断:nest-cli.json 配置后自动为 DTO 属性添加 @ApiProperty
  • 安全方案:@ApiBearerAuth() / @ApiOAuth2() / @ApiCookieAuth() + DocumentBuilder.addBearerAuth()
  • 映射类型:PartialType, PickType, OmitType(从 @nestjs/swagger 导入以保留 API 元数据)
  • 多 Spec 端点:通过 include 选项为不同模块生成独立文档
  • 文件上传文档:@ApiConsumes('multipart/form-data') + @ApiBody()
  • Schema 组合:oneOf, anyOf, allOf + getSchemaPath()
  • 全局参数/响应:DocumentBuilder.addGlobalParameters(), addGlobalResponse()

[基础] 单元测试

  • @nestjs/testingTest.createTestingModule({ providers: [CatsService] }).compile()
  • .get(CatsService) 获取待测实例
  • .overrideProvider(CatsRepository).useValue(mockRepo) mock 依赖
  • useMocker() 自动 mock 所有未注册依赖
  • Jest 集成:jest.fn(), jest.spyOn(), expect().toHaveBeenCalledWith()

[中阶] E2E 测试与高级 Mock

  • E2E 测试:module.createNestApplication() 创建完整应用
  • supertest 发送 HTTP 请求:request(app.getHttpServer()).get('/cats').expect(200)
  • .overrideGuard(AuthGuard).useValue({ canActivate: () => true }):跳过认证
  • .overrideModule(ConfigModule).useModule(TestConfigModule):替换整个模块
  • Suites(Automock):TestBed.solitary(CatsService) 自动生成类型安全 mock
  • REPL 模式:npm run start -- --entryFile replget(CatsService) 交互式调试

[高阶] 测试进阶

  • Request-scoped provider 测试:ContextIdFactory.getByRequest 控制 DI 子树
  • 微服务测试:module.createNestMicroservice()
  • 全局 Guard 测试:APP_GUARD 使用 useExisting 使 Guard 可被 override
  • setLogger() 自定义测试日志
  • Compodoc:npx @compodoc/compodoc -p tsconfig.json -s 生成项目文档
  • CRUD Generator:nest g resource cats 一键生成完整 CRUD + 测试骨架

[资深] 源码:测试模块

  • packages/testing/testing-module.builder.tsTestingModuleBuilder 的 override 链实现
  • packages/testing/testing-module.tsTestingModule 扩展了 NestApplicationContext
  • useMocker 如何通过 DI 元数据自动生成 mock

[架构] 质量保障策略

  • API 文档即合约:Swagger/OpenAPI 作为前后端协作的 Single Source of Truth
  • 测试金字塔:单元测试(70%)→ 集成测试(20%)→ E2E 测试(10%)
  • 测试覆盖率目标:80%+ 代码覆盖率
  • 契约测试:确保微服务接口兼容性

课后实践

  • 为 REST API 添加完整 Swagger 文档,确保所有端点、DTO、响应都有文档
  • 为 CatsService 编写单元测试(mock Repository),覆盖 CRUD + 异常路径
  • 编写一个 E2E 测试覆盖完整认证 + CRUD 流程

第二十课:生产部署与架构设计

覆盖文档:Deployment, Performance(Fastify), Health Checks, Serverless, HTTPS, Keep-Alive, Common Errors, DevTools, CQRS, Async Local Storage, Nest Commander, SWC/Hot Reload, Sentry 前置知识:全部前序课程 文档页数:15+ 页 | 核心主题:6

课程内容

[基础] 构建与部署基础

  • 构建:npm run builddist/main.js
  • 运行:NODE_ENV=production node dist/main.js
  • Dockerfile 编写(多阶段构建):
    FROM node:20 AS builder
    WORKDIR /app
    COPY package*.json ./
    RUN npm ci
    COPY . .
    RUN npm run build
    
    FROM node:20-slim
    WORKDIR /app
    COPY --from=builder /app/dist ./dist
    COPY --from=builder /app/node_modules ./node_modules
    EXPOSE 3000
    CMD ["node", "dist/main"]
    
  • .dockerignore:排除 node_modules.gitdist
  • 健康检查:@nestjs/terminus
    • TerminusModuleHealthCheckService@HealthCheck() 装饰器
    • 内置指标:HttpHealthIndicatorTypeOrmHealthIndicatorDiskHealthIndicatorMemoryHealthIndicator
    • 自定义 HealthIndicator:HealthIndicatorService

[中阶] 生产最佳实践

  • 环境变量:不硬编码,使用 ConfigService
  • 日志:JSON 格式 + 关联 ID(Correlation ID)
  • forceCloseConnections: true:优雅关闭时不等待 Keep-Alive 连接
  • HTTPS:NestFactory.create(AppModule, { httpsOptions: { key, cert } })
  • 多服务器:同时监听 HTTP(重定向)+ HTTPS
  • 全局路径前缀:app.setGlobalPrefix('api', { exclude: ['health'] })
  • Raw Body:{ rawBody: true } 用于 Webhook 签名验证
  • 性能:SWC 编译(20x 加速),Fastify 平台(2x 吞吐)
  • 错误追踪:@sentry/nestjsSentryModule.forRoot() + SentryGlobalFilter

[中阶] 扩展与运维

  • 垂直扩展(Scale Up):增加单服务器资源
  • 水平扩展(Scale Out):多实例 + 负载均衡(Nginx / AWS ELB)
  • Docker Compose 编排多服务
  • CI/CD 流水线:构建 → 测试 → 镜像推送 → 部署

[高阶] Serverless 与特殊场景

  • Serverless 部署(AWS Lambda):
    • @codegenie/serverless-express 适配
    • 冷启动优化:LazyModuleLoader 按需加载模块
  • CLI 应用:nest-commanderCommandRunner + @Command() + @Option()
  • AsyncLocalStorage(nestjs-cls):替代 Request-scoped provider,无 Scope 冒泡开销
  • REPL 调试:运行时交互式探索 DI 容器
  • 常见错误排查:
    • "Cannot resolve dependency":检查 providers 数组、forwardRefNEST_DEBUG=true
    • 循环文件导入:避免 barrel file(index.ts)

[资深] 性能调优与 DevTools

  • SWC vs tsc:SWC 是 Rust 编译器,不做类型检查,需配合 --type-check
  • Fastify 适配器源码:packages/platform-fastify/adapters/fastify-adapter.ts
  • 请求管线性能分析:每层增强器的开销测量
  • NestJS DevTools:依赖图可视化、路由导航、交互式 Playground、CI/CD 集成

[架构] 系统架构设计

  • 单体到微服务的演进路径

    阶段1:NestJS 单体应用(模块化设计)
        ↓ 流量增长,团队扩大
    阶段2:NestJS 混合应用(HTTP + 内部微服务)
        ↓ 独立部署需求
    阶段3:NestJS 微服务集群(独立部署 + 消息总线)
        ↓ 前端查询复杂度增加
    阶段4:API Gateway + GraphQL Federation + 微服务
    
  • CQRS 架构@nestjs/cqrs):

    • Command(写操作)→ CommandBus → CommandHandler → EventBus → EventHandler
    • Query(读操作)→ QueryBus → QueryHandler
    • Saga:@Saga() 监听事件流,触发后续命令
    • AggregateRoot:事件溯源基类
  • NestJS 技术栈全景图

    ┌─────────────────────────────────────────────────────┐
    │                    客户端                             │
    │  Web App / Mobile App / 第三方服务                     │
    └─────────────────┬───────────────────────────────────┘
                      │
    ┌─────────────────┴───────────────────────────────────┐
    │              API Gateway / BFF                       │
    │  NestJS + GraphQL Federation / REST + Swagger        │
    │  认证(JWT) + 限流(Throttler) + CORS + Helmet         │
    └──────┬──────────┬──────────┬────────────────────────┘
           │          │          │
    ┌──────┴───┐ ┌────┴────┐ ┌──┴────────┐
    │ 用户服务  │ │ 订单服务 │ │ 支付服务   │
    │ NestJS   │ │ NestJS  │ │ NestJS    │
    │ TypeORM  │ │ Prisma  │ │ Mongoose  │
    │ PostgreSQL│ │ MySQL   │ │ MongoDB   │
    └──────┬───┘ └────┬────┘ └──┬────────┘
           │          │          │
    ┌──────┴──────────┴──────────┴────────────────────────┐
    │              消息总线                                 │
    │  RabbitMQ / Kafka / NATS / Redis                     │
    └─────────────────────────────────────────────────────┘
           │
    ┌──────┴──────────────────────────────────────────────┐
    │              基础设施                                 │
    │  Redis(缓存) + BullMQ(队列) + Cron(定时)              │
    │  Sentry(监控) + ELK(日志) + Prometheus(指标)          │
    │  Docker + K8s + CI/CD                                │
    └─────────────────────────────────────────────────────┘
    
  • 技术决策清单

    决策点推荐方案备选方案
    HTTP 引擎Express(生态)Fastify(性能)
    ORMPrisma(新项目)TypeORM(成熟项目)
    认证@nestjs/jwtPassport(多策略)
    缓存Redis + cache-manager内存缓存(单实例)
    队列BullMQRabbitMQ / Kafka
    API 风格REST + SwaggerGraphQL(复杂前端)
    微服务通信gRPC(内部 RPC)NATS / Kafka(事件)
    部署Docker + K8sServerless(低流量)

课后实践

  • 为应用编写 Dockerfile(多阶段构建),用 docker-compose.yml 编排应用 + 数据库 + Redis
  • 添加 @nestjs/terminus 健康检查端点
  • 实现优雅关闭:enableShutdownHooks() + 数据库连接清理
  • 将应用从 Express 切换为 Fastify,验证所有功能正常

附录 A:知识点与课程映射表

文档章节覆盖课程
Introduction, First Steps第1课
Controllers第2课
Providers第3课
Modules第4课
Middleware第5课
Exception Filters第5课
Pipes, Validation第6课
Guards第7课
Interceptors第7课
Custom Decorators第8课
Custom Providers, Async Providers第3课 + 第9课
Dynamic Modules第4课
Injection Scopes第9课
Circular Dependency第9课
Module Reference第9课
Lazy-loading Modules第4课 + 第20课
Execution Context第7课 + 第8课
Lifecycle Events第9课
Discovery Service第8课
Platform Agnosticism第1课 + 第9课
Testing第19课
Configuration第13课
Database / MongoDB第10课
Serialization第10课
Versioning第2课
Caching第14课
Task Scheduling第14课
Queues第14课
Logger第13课
Cookies / Session第13课
Events第13课
Compression第15课
File Upload / Streaming第15课
HTTP Module第15课
MVC / Serve Static第15课
Performance (Fastify)第20课
Server-Sent Events第15课
Authentication第11课
Authorization第11课
Encryption and Hashing第12课
Helmet / CORS / CSRF第12课
Rate Limiting第12课
GraphQL(18 页)第18课
WebSockets(6 页)第16课
Microservices(12 页)第17课
CLI(5 页)第1课 + 第4课
OpenAPI(8 页)第19课
REPL第19课
CRUD Generator第2课 + 第19课
SWC / Hot Reload第1课 + 第20课
Passport第11课
ORM Recipes第10课
Health Checks第20课
CQRS第20课
Sentry第20课
Nest Commander第20课
Async Local Storage第20课
Serverless第20课
HTTP Adapter第1课
Keep-Alive / Global Prefix / Raw Body第20课
Hybrid Application第17课
HTTPS & Multiple Servers第20课
Request Lifecycle第5课 + 第7课
Common Errors第20课
Deployment第20课
DevTools第20课

附录 B:各课程适合的用户收获速查

课程基础用户收获中阶用户收获高阶用户收获资深用户收获架构用户收获
第1课能创建并运行项目掌握工程化配置理解多平台抽象读懂 NestFactory 源码完成技术选型评估
第2课能写 CRUD 路由掌握高级路由技巧实现 API 版本控制读懂路由注册源码设计 RESTful API 规范
第3课能用 Service 注入掌握 4 种 Provider 模式异步/条件 Provider读懂 DI 容器源码IoC/DI 设计模式决策
第4课能组织功能模块模块共享与重导出动态模块 forRoot读懂模块扫描源码模块化架构设计
第5课能用中间件和抛异常自定义异常过滤器平台无关异常处理读懂异常处理源码错误处理策略设计
第6课能用内置管道验证class-validator/Zod自定义转换管道读懂管道执行源码验证策略选型
第7课能用 Guard 做鉴权角色守卫 + 拦截器ExecutionContext 深入读懂管线组装源码横切关注点设计
第8课能写自定义装饰器装饰器组合Discovery Service读懂元数据系统源码元数据驱动架构
第9课理解 3 种 Scope生命周期钩子ModuleRef + forwardRef读懂作用域源码多租户架构设计
第10课能接入 TypeORMMongoose/Prisma多数据库/事务/序列化Repository 源码模式数据层架构选型
第11课能实现 JWT 认证Passport + RBACCASL 细粒度权限认证模块源码认证架构设计
第12课能配置 Helmet+CORSCSRF + 限流加密与哈希原理Node.js crypto 深入安全架构设计
第13课能用配置和日志自定义 Logger + 事件Session + CookieConfigModule 源码基础设施架构
第14课能用缓存定时任务 + 队列队列进阶 + Flow调度/队列源码异步处理架构
第15课能上传文件HTTP 客户端 + SSEMVC + 静态文件StreamableFile 源码文件与通信策略
第16课能写 WS 网关Socket.IO 进阶自定义适配器WS 模块源码实时通信架构
第17课TCP 微服务通信7 种传输层自定义传输 + 混合应用微服务抽象源码分布式系统设计
第18课GraphQL 入门类型系统 + 订阅Federation + 复杂度GraphQL 模块源码GraphQL 架构策略
第19课Swagger 文档E2E 测试高级 Mock + REPL测试模块源码质量保障策略
第20课Docker 部署生产最佳实践Serverless + CQRSDevTools + 性能调优系统架构全景图