88
大概图解
plaintext
src/
├── config/ # 配置文件目录
│ ├── database.config.ts
│ ├── jwt.config.ts
│ └── app.config.ts
│
├── modules/ # 业务模块目录
│ ├── users/ # 用户模块
│ │ ├── dto/ # 数据传输对象
│ │ ├── entities/ # 数据库实体
│ │ ├── interfaces/ # 接口定义
│ │ ├── users.controller.ts
│ │ ├── users.service.ts
│ │ ├── users.module.ts
│ │ └── users.repository.ts
│ │
│ └── auth/ # 认证模块
│ ├── dto/
│ ├── strategies/ # 认证策略
│ ├── guards/ # 守卫
│ ├── auth.controller.ts
│ ├── auth.service.ts
│ └── auth.module.ts
│
├── common/ # 公共代码目录
│ ├── decorators/ # 自定义装饰器
│ ├── filters/ # 异常过滤器
│ ├── guards/ # 全局守卫
│ ├── interceptors/ # 拦截器
│ ├── middlewares/ # 中间件
│ └── pipes/ # 管道
│
├── shared/ # 共享模块目录
│ ├── services/ # 共享服务
│ └── utils/ # 工具函数
│
├── database/ # 数据库相关
│ ├── migrations/ # 数据库迁移文件
│ └── seeds/ # 数据库种子文件
│
├── app.module.ts # 应用程序根模块
├── app.controller.ts # 应用程序根控制器
├── app.service.ts # 应用程序根服务
└── main.ts # 应用程序入口文件
test/ # 测试目录
├── e2e/ # 端到端测试
└── unit/ # 单元测试
├── .env # 环境变量文件
├── .env.development
├── .env.production
├── package.json
├── tsconfig.json
├── nest-cli.json
└── README.mdModule
每个模块都会包含 controller、service、module、dto、entities 这些东西
controller 是处理路由,解析请求参数的。
service 是处理业务逻辑的,比如操作数据库。
dto 是封装请求参数的。
entities 是封装对应数据库表的实体的。
Controllers && Services
对于某个Module来说,Controllers是接收请求的入口,Services则是方法实现
Provider
Controllers是如何调用Services的呢?
- 当Services成为Provider时**
Import
typescript
// pokemon.module.ts
// 推荐
@Module({
controllers: [PokemonController],
providers: [PokemonService],
imports: [PrismaModule],
exports: [PokemonService],
})
// 不推荐
@Module({
controllers: [PokemonController],
providers: [PokemonService, PrismaService],
imports: [],
exports: [PokemonService],
})Import vs Provider
区别在于:import module会复用已经创建的实例,而每个provider都会创建新的实例。
前者占用更少的内存,且一个可复用的实例在多处被使用在需求中也更加常见。
Summary
看一个Nestjs应用就是看明白Module之间是如何互相作用的。
- 定义自己的controllers
- 定义自己的service
- 把自己的service放在providers中,这样controllers才能用service
- 如果需要用外部的service,将外部module放在imports里
- 如果自己的service也需要被其他module使用,将自己的service放到exports里
生命周期
Nest 从接收到请求,到返回响应的这个流程,有很多切面,路由最终是在 cotnroller 的方法,也就是 handler 里处理的。
在 main.ts 里调用 NestFactory.create 方法,就会从 AppModule 开始递归解析 Module,实例化其中的 provider、controller,并依次调用它们的 onModuleInit 生命周期方法。
之后会再递归调用每个 Module 的 provider、controller 的还有 Module 自身的 onApplicationBootstrap 生命周期方法。
Nest 销毁的时候,也会依次调用 Module 的 provider、controller 还有 Module 自己的 onModuleDestroy 方法、beforeApplicationShutdown 还有 onApplicationShutdown 的生命周期方法。
文章参考
