动态模块
Nest 中的动态模块允许你创建可在运行时配置的模块,而不是使用静态的固定配置。当你需要提供灵活、可定制的模块时,这尤其有用。
使用场景
在项目中有用户(UserModule)、书籍(BookModule)等模块,我希望通过 json 文件来存储对应模块数据。 这个时候就可以定义一个存储模块(DbModule),用来定义存储的读取和写入方法,其他模块在使用存储模块时,传入 json 文件路径。

在 UserModule 里用的时候,path 是 users.json,在 BookModule 用的时候,path 是 books.json。
这个 DbModule 就是动态模块
创建动态模块
1. 定义动态模块
ts
import { DynamicModule, Module } from '@nestjs/common';
import { DbService } from './db.service';
export interface DbModuleOptions {
path: string
}
@Module({})
export class DbModule {
static register(options: DbModuleOptions): DynamicModule {
return {
module: DbModule,
providers: [
{
provide: "OPTIONS",
useValue: options
},
DbService,
],
exports: [DbService]
}
}
}
该方法返回一个 DynamicModule 对象,包含以下属性:
-
module: 指定这个动态模块对应的类
-
providers: 定义该模块提供的服务
-
把传入的 options 用 useValue 来声明为 provider;token 为 OPTIONS。
记住 provide 定义的值,后面要考(会用到)
-
DbService 中实现读取和写入方法
-
-
exports: 指定哪些服务可以被导入该模块的其他模块使用
2. 定义动态模块对应的 service
service 中实现读取和写入方法,注入
ts
import { Inject, Injectable } from '@nestjs/common';
import { DbModuleOptions } from './db.module';
import { access, readFile, writeFile } from 'fs/promises';
@Injectable()
export class DbService {
@Inject('OPTIONS')
private options: DbModuleOptions;
// 读取
async read() {
const filePath = this.options.path;
// 读取文件内容
const str = await readFile(filePath, { encoding: 'utf-8' });
// 转为对象
return JSON.parse(str);
}
// 写入
async write(obj: Record<string, any>) {
await writeFile(this.options.path, JSON.stringify(obj || []), {
encoding: 'utf-8',
});
}
}
使用动态模块
在 UserModule 中使用
ts
import { Module } from '@nestjs/common';
import { UserService } from './user.service';
import { UserController } from './user.controller';
import { DbModule } from 'src/db/db.module';
@Module({
imports: [
DbModule.register({
path: 'users.json',
}),
],
controllers: [UserController],
providers: [UserService],
})
export class UserModule {}
在 UserService 中使用就和静态模块一样了
js
import { Inject, Injectable } from '@nestjs/common';
import { DbService } from '../db/db.service';
import { User } from './entities/user.entity';
@Injectable()
export class UserService {
@Inject(DbService)
dbService: DbService;
async register() {
// 读取
const users = await this.dbService.read();
// ...
// 写入
await this.dbService.write(user)
return user
}
}