NestJs如何实现providers动态注入 批量引入无需逐个声明导入
解决方案
方案1:基于文件系统动态批量导入(原生实现,无额外依赖)
你可以通过Node.js内置的fs和path模块遍历指定目录下的service、resolver文件,自动导入后合并到providers数组中,示例代码如下:
首先编写批量导入逻辑:
import * as fs from 'fs'; import * as path from 'path'; // 配置存放service/resolver的目录路径,此处以src/worker目录为例 const MODULE_DIR = path.join(__dirname, './worker'); // 匹配规则:仅导入.service.ts和.resolver.ts后缀的文件 const FILE_PATTERN = /\.(service|resolver)\.ts$/; export const getAllModules = () => { const providers = []; // 遍历目录下的所有文件 const files = fs.readdirSync(MODULE_DIR); files.forEach(file => { if (FILE_PATTERN.test(file)) { // 导入文件模块 const moduleExports = require(path.join(MODULE_DIR, file)); // 兼容默认导出和命名导出 Object.values(moduleExports).forEach(exportItem => { if (typeof exportItem === 'function') { // 过滤出类定义 providers.push(exportItem); } }); } }); return providers; };
在Module中直接使用即可:
import { getAllModules } from './get-all-modules'; const allModules = getAllModules(); @Module({ // ...其他配置 providers: [ ...allModules // 有特殊不需要批量导入的provider可在此处额外追加 ] }) export class WorkerModule {}
方案2:基于ES模块的glob导入(适用于支持ES模块的项目)
如果你的项目使用Vite构建,或者Node版本 >=14.13 支持ES模块,可以用更简洁的glob导入语法:
// 导入所有service和resolver文件 const modules = import.meta.glob('./worker/**/*.{service,resolver}.ts', { eager: true }); const allModules = Object.values(modules).flatMap(module => Object.values(module).filter(item => typeof item === 'function') ); @Module({ // ...其他配置 providers: [...allModules] }) export class WorkerModule {}
注意事项
- 如果使用TypeScript编译后运行,需要注意编译后的js文件路径和后缀匹配规则,可将匹配规则调整为
/\.(service|resolver)\.(ts|js)$/兼容编译前后的环境 - 批量导入和手动导入的DI规则完全一致,依然需要注意处理循环依赖问题
- 如果你的项目使用了Webpack等打包工具打包为单文件部署,需要配置打包规则保留对应目录的文件结构,或者调整为基于导入上下文的动态导入方案
- 对于需要指定作用域的provider,不建议放在批量导入规则中,建议单独声明
- import.meta.glob是ES模块的特性,CommonJS环境下无法使用,需要根据项目的模块规范选择方案
- TypeScript环境下如果提示
require未定义,安装@types/node依赖即可解决
内容的提问来源于stack exchange,提问作者user2167582
相关产品推荐
相关产品推荐

