使用 Dynamic Module
很多情况下,我们希望在引入模块时传一些参数,动态生成模块的内容。
这就用到 Dynamic Module 了。
示例
使用 cli 创建一个 module。
bash1nest generate module MyFirst --no-spec 2 3CREATE src/my-first/my-first.module.ts (84 bytes) 4UPDATE src/app.module.ts (322 bytes)
生成后的的代码是这样的:
typescript1import { Module } from '@nestjs/common' 2 3@Module({}) 4export class MyFirstModule {}
一个是 @Module 装饰器,还一个是 Module 的 class。
实现动态 Module 的方法就是实现一个 register 方法:
typescript1export class MyFirstModule { 2 static register(options: Record<string, any>): DynamicModule { 3 const optionProvider = { 4 provide: 'CONFIG_OPTIONS', 5 useValue: options, 6 } 7 return { 8 module: MyFirstModule, 9 providers: [optionProvider], 10 exports: [optionProvider], 11 } 12 } 13}
这个动态 Module 的 provider 是返回一个注册 Module 时传入的 options 对象。
接着在需要引入的 Module 中调用 register方法:
typescript1import { MyFirstModule } from './my-first/my-first.module' 2 3@Module({ 4 imports: [MyFirstModule.register({ name: 'Dynamic Module' })], 5 controllers: [AppController], 6 providers: [AppService], 7}) 8export class AppModule {}
在引入动态 Module 时,传入{ name: 'Dynamic Module' },它内部的 CONFIG_OPTIONS provider 也就有了固定值。
现在在 AppService 中,已经可以使用 MyFirstModule 的 token 为 “CONFIG_OPTIONS” 的 Provider 了。
typescript1import { Inject, Injectable } from '@nestjs/common' 2 3@Injectable() 4export class AppService { 5 constructor(@Inject('CONFIG_OPTIONS') private readonly options: Record<string, any>) {} 6 7 getHello(): string { 8 console.log(this.options) 9 return 'Hello World!' 10 } 11}
通过访问http://localhost:3000/,你将在终端看到结果:

动态 Module 的用法大致如此。
方法名
register 方法并非强制规定,想叫啥都是可以的,只要保证在引入时调用这个方法即可。
但为了规范性,nest 约定了三个方法名:
- register:用一次模块传一次配置,比如这次调用是
BbbModule.register({aaa:1}),下一次就是BbbModule.register({aaa:2})了。 - forRoot:配置一次模块用多次,一般出现在 AppModule 里。
- forFeature:用了 forRoot 固定了整体模块,用于局部的时候,可能需要再传一些配置,比如用 forRoot 指定了数据库链接信息,再用 forFeature 指定某个模块访问哪个数据库和表。
总结
Module 可以传入 options 动态产生,这叫做动态 Module。
动态 Module 通过在 Module class 中定义 static 方法来实现。
建议的 Module 的方法名有 register、forRoot、forFeature 3 种。
这些方法还可以写成 xxxAsync 版本,也就是传入 useFactory 等 option,内部注册异步 provider。
在后续的数据库、ORM 接入时,会大量使用动态 Module。