序章
NestJS 从现象到本质的思维旅程
第一阶段:理解 Nest 的核心架构模型
- 装饰器不只是语法糖:Nest 如何解析
@Controller()?
元数据收集(Reflect.metadata)与模块扫描的启动流程 - Module:为什么每个应用都必须有一个根模块?
@Module装饰器如何构建依赖图谱?providers、controllers、imports的作用 - 组件注册:
@Injectable()真的只是个标记吗?
它如何让类成为 DI 容器的“可注入目标”? - 全局模块:
forRoot()和@Global()的区别是什么?
何时该用单例注入,何时该按需导入? - 动态模块:
forFeature()的设计哲学
如何实现数据库模块的按需配置与多连接支持?
第二阶段:深入依赖注入(DI)容器机制
- DI 容器的本质:Map<token, instance>?
Nest 的Container与ModuleRef如何管理实例生命周期 - Provider 的多种写法:
useClass、useValue、useFactory、useExisting
它们的适用场景与内部解析逻辑 - 自定义 Provider Token:字符串 vs Symbol vs 类型
为什么推荐用InjectionToken?如何避免命名冲突? - 循环依赖的三种解法:
forwardRef、模块拆分、延迟注入
Nest 如何通过临时占位解决 A 依赖 B、B 依赖 A 的问题? - Scope:默认 singleton 之外,request-scoped 实例如何工作?
每次请求都新建实例?内存开销与性能权衡
第三阶段:解构控制器与请求生命周期
- 路由匹配:从
@Get('/users/:id')到参数提取
Path-to-RegExp 如何解析动态参数?req.params的来源 - 参数装饰器原理:
@Body()、@Param()、@Query()如何工作?
它们如何通过元数据告诉框架“这个参数从哪来”? - 管道(Pipe)的执行时机:在 handler 之前拦截
ValidationPipe如何结合 class-validator 实现自动校验? - 异常过滤器(Filter):如何统一处理抛出的
HttpException?
拦截错误,返回 JSON 响应,替换默认错误格式 - 守卫(Guard)与拦截器(Interceptor)的执行顺序
请求进来时:Guard → Interceptor → Pipe → Controller → Interceptor → 返回
第四阶段:探索高级特性与运行时机制
- AOP 编程:守卫、拦截器、装饰器如何实现横切关注点?
日志、权限、缓存、性能监控的统一注入方式 - 拦截器中的
handle():Observable 流的魔法
为什么能用 RxJS 操作请求/响应流?switchMap实现异步转换 - 自定义装饰器:如何创建
@CurrentUser()?
结合@SetMetadata()与守卫,实现上下文注入 - 微服务通信:
ClientProxy如何封装 TCP/RMQ/Kafka?emit()vssend():事件驱动与请求响应模式的区别 - WebSocket 网关:
@WebSocketGateway()如何集成 Socket.IO?
连接管理、会话状态、广播机制的实现
第五阶段:揭秘编译时与工具链机制
- Nest CLI 的代码生成原理:
nest g service user发生了什么?
AST 操作?模板填充?如何自动注册到模块? - 依赖注入的静态分析:为什么
constructor(private userService: UserService)能自动注入?
TypeScript 的emitDecoratorMetadata如何暴露类型信息 - 反射元数据(Reflect Metadata)的底层机制
@SetMetadata('roles', ['admin'])存在哪?如何读取? - 平台无关性:Nest 如何支持 Express 与 Fastify?
AbstractHttpAdapter如何抽象底层 HTTP 服务器?
第六阶段:深入企业级架构与最佳实践
- 模块划分:领域驱动设计(DDD)在 Nest 中的落地
UserModule、OrderModule、SharedModule的职责边界 - CQRS 模式:Command 与 Query 的分离实现
使用@nestjs/cqrs实现事件溯源与命令总线 - 健康检查与
Terminus
如何暴露/health端点,检查数据库、Redis 是否可用? - 配置管理:
ConfigService如何加载.env文件?
多环境配置、验证、注入时机 - 测试金字塔:E2E 测试如何启动完整应用?
Test.createTestingModule()与supertest的协作