NestJs封装库时DiscoveryService报错:无法解析ModulesContainer依赖
我在NestJS项目里开发了一个用到DiscoveryService的模块,原本运行完全正常,但按照官方文档把它封装成Nest库之后,就出现了依赖解析错误,提示找不到DiscoveryService需要的ModulesContainer。我试过在模块的imports和providers里添加ModulesContainer,问题还是没解决。
错误信息
Nest can't resolve dependencies of the DiscoveryService (?). Please make sure that the argument ModulesContainer at index [0] is available in the DiscoveryModule context.
潜在解决方案提示:
- 如果ModulesContainer是提供者,它是否属于当前DiscoveryModule?
- 如果ModulesContainer从独立@Module导出,该模块是否已在DiscoveryModule中导入?@Module({ imports: [ /* 包含ModulesContainer的模块 */ ] })
相关代码
库模块代码
import { DiscoveryService } from '@nestjs/core'; @Injectable() export class EventPublishingService { private readonly logger = new Logger(EventPublishingService.name); private readonly publishingEventProviders; constructor( private discoveryService: DiscoveryService ) { this.publishingEventProviders = this.discoveryService .getProviders() .filter( ({ metatype }) => metatype && Reflect.getMetadata(PUBLISHABLE_METADATA, metatype), ); } } @Global() @Module({ imports: [DiscoveryModule, HttpModule, ConfigModule], providers: [ EventRegistrationService, EventManagerServiceApi, EventPublishingService], exports: [EventPublishingService], }) export class EventManagerModule {}
主应用模块代码
@Module({ imports: [ ConfigModule.forRoot({ isGlobal: true, cache: true, load: [configuration], }), ScheduleModule.forRoot(), MongooseModule.forRootAsync({ imports: [DataVaultManagerModule], inject: [DataVaultManager], useClass: MongooseConfigService, }), ParticipantsModule, StudiesModule, HealthModule, EventManagerModule, UsersModule, ], controllers: [AppController], providers: [ AppService, { provide: APP_PIPE, useClass: ZodValidationPipe, }, ], }) export class AppModule {}
解决方案
1. 调整库的依赖声明
把库的package.json中@nestjs/core、@nestjs/common这类核心依赖移到peerDependencies里,不要放在dependencies中。这样库会复用主应用的NestJS核心包,避免依赖隔离或版本冲突:
{ "peerDependencies": { "@nestjs/common": "^10.0.0", "@nestjs/core": "^10.0.0", "@nestjs/axios": "^3.0.0", "@nestjs/config": "^3.0.0" } }
2. 延迟DiscoveryService的调用时机
不要在服务的构造函数里直接调用DiscoveryService,因为此时Nest应用可能还没初始化完成,无法正确获取提供者。改用OnModuleInit生命周期钩子执行逻辑:
import { Injectable, OnModuleInit, Logger } from '@nestjs/common'; import { DiscoveryService } from '@nestjs/core'; @Injectable() export class EventPublishingService implements OnModuleInit { private readonly logger = new Logger(EventPublishingService.name); private publishingEventProviders; constructor( private discoveryService: DiscoveryService ) {} onModuleInit() { this.publishingEventProviders = this.discoveryService .getProviders() .filter( ({ metatype }) => metatype && Reflect.getMetadata(PUBLISHABLE_METADATA, metatype), ); } }
3. 检查库的构建配置
如果用@nestjs/cli构建库,确认nest-cli.json里的库配置正确,没有错误隔离核心依赖:
{ "projects": { "event-manager": { "type": "library", "root": "libs/event-manager", "entryFile": "index", "sourceRoot": "libs/event-manager/src", "compilerOptions": { "tsConfigPath": "libs/event-manager/tsconfig.lib.json" } } } }
4. 主应用中验证依赖导入
虽然库模块已经导入了DiscoveryModule,但如果主应用有特殊的模块隔离设置,可以尝试在根模块中显式导入DiscoveryModule(多数情况下不需要,但可以作为排查手段)。
内容的提问来源于stack exchange,提问作者Chathura J

