1. 什么是Module
每个 Nest 应用程序至少有一个模块,即根模块。根模块是 Nest 开始安排应用程序树的地方。事实上,根模块可能是应用程序中唯一的模块,特别是当应用程序很小时,但是对于大型程序来说这是没有意义的。在大多数情况下,您将拥有多个模块,每个模块都有一组紧密相关的功能。
// 如果你需要把这个模块 暴露到全局使用可以加 一个装饰器 @Global
// 使一切全局化并不是一个好的解决方案。 全局模块可用于减少必要模板文件的数量。 `imports` 数组仍然是使模块 API 透明的最佳方式。
@Global()
@Module({
imports:[], // 可以注入 其他module 或者provider
exports:[], // 如果你这个模块中的provider 要在别的模块中使用 你必须要在这里声明 导出这鞋provider ,当然 你也可以把 这个module导出其他地方import 一下这样其他模块中的provider 也是可以使用的
providers:[] // 由 Nest 注入器实例化的提供者,并且可以至少在整个模块中共享
})
2. 如何使用
1. 共享模块
user.module.ts 导出
@Module({
controllers: [UserController],
providers: [UserService],
exports: [UserService],
})
export class UserModule {}
app.module.ts 导入 导入module
import { UserModule } from './user/user.module';
import { OrderModule } from './order/order.module';
@Module({
imports: [UserModule, OrderModule],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
app.controller.ts 使用
import { UserService } from './user/user.service';
@Controller()
export class AppController {
constructor(
private readonly appService: AppService,
private readonly userService: UserService,
) {}
@Get('user')
getUser(): string {
return this.userService.findAll();
}
}
2. 全局模块
@Global()进行module修饰
user.module.ts 必须进行导出
import { Global, Module } from '@nestjs/common';
import { UserService } from './user.service';
import { UserController } from './user.controller';
@Global()
@Module({
controllers: [UserController],
providers: [UserService],
exports: [UserService], // 必须进行导出
})
export class UserModule {}
在order 模块使用无须在module imports导入
order.controller.ts
import { UserService } from '../user/user.service';
@Controller('order')
export class OrderController {
constructor(
private readonly orderService: OrderService,
private readonly userService: UserService,
) {}
@Get('user')
getUser() {
return this.userService.findAll();
}
}
3. 动态导入
在 Nest.js 中,动态导入(Dynamic Module)是指能够在运行时动态加载和注入模块的功能。相比于静态导入,动态导入提供更大的灵活性,因为我们可以在运行时决定使用哪些模块或配置,而不需要在编译时确定。
通常情况下,我们会将服务和组件包含在 Nest.js 的模块中,并将它们使用 @Module
装饰器注册为一个静态模块。但是,在某些场景下,我们可能需要将服务和组件按需导入,或按照特定条件进行组合。这时就可以使用动态导入。
动态导入允许我们以 programmatic 的方式创建和组成 Nest.js 的模块,并通过调用 forRoot
或 forFeature
方法来注册服务和组件。forRoot
方法允许我们在导入模块并使用特定配置对象时创建模块,而 forFeature
允许我们在模块之间共享模块的特定部分。
动态导入模块的几个特点和优点:
- 动态导入允许我们在运行时动态加载和注册模块,从而允许更灵活的应用程序设计和建模。
- 动态导入模块提供了一种方便的方式,在不同的模块之间共享服务和组件。
- 动态导入允许我们根据特定的条件实现按需导入和使用模块。
- 动态加载模块允许我们创建可扩展、可维护和可重用的应用程序,从而提高了应用程序的复用性和可测试性。
案例
config.module.ts 导出
import { Module, Global, DynamicModule } from '@nestjs/common';
export interface Options {
path: string;
}
@Global()
@Module({})
export class ConfigModule {
static forRoot(options: Options): DynamicModule {
return {
module: ConfigModule,
providers: [
{
provide: 'Config',
useValue: { baseApi: '/api' + options.path },
},
],
exports: [
{
provide: 'Config',
useValue: { baseApi: '/api' + options.path },
},
],
};
}
}
=================== 原写法 ================
@Module({
controllers: [ConfigController],
providers: [ConfigService]
})
export class ConfigModule {}
app.module.ts 导入
import { ConfigModule } from './config/config.module';
@Module({
imports: [ConfigModule.forRoot({ path: '/666' })],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
app.controller.ts 使用 Inject对应先前定义的provide
import { Controller, Get, Inject } from '@nestjs/common';
@Controller()
export class AppController {
constructor(
@Inject('Config') private readonly value: object,
) {}
@Get()
getHello(): object {
return this.value;
}
}
总结
-
定义自己的controllers
-
定义自己的service
-
把自己的service放在providers中,这样controllers才能用service
-
如果需要用外部的service,将外部module放在imports里
-
如果自己的service也需要被其他module使用,将自己的service放到exports里