NestJs:动态模块 IoC 范围

NestJs: dynamic module IoC scope

The NestJs documentation on Modules states that:

In Nest, modules are singletons by default, and thus you can share the same instance of any provider between multiple modules effortlessly.

The NestJs documentation on DynamicModules states that:

In fact, what our register() method will return is a DynamicModule. A dynamic module is nothing more than a module created at run-time, with the same exact properties as a static module, plus one additional property called module.

How does the framework manage the lifetime of DynamicModules?

一般来说,就像它对任何其他模块一样。动态模块只是由函数配置并由对象表示的模块的特殊名称。最终结果通常类似于

{
  module: SomeModuleClass,
  imports: [Imports, For, The, Module],
  providers: [SomeProviderToken, SomeProviderService, ExtraProvidersNeeded],
  exports: [SomeProviderService],
}

与您在 @Module() 装饰器中看到的几乎相同,但通过可能使用 DI 而不是直接编写的函数进行配置

How can you share multiple dynamic module instances between modules?

我可能需要在这里做一些澄清,但一旦我知道这里的目标是什么,或者你想做什么,我会很乐意更详细地编辑我的答案。

How can you manage/change the scope of DynamicModules? For exmaple, changing them from behaving transitively to as a singleton. Defining their injection token, retrieving them on demand, etc.

共享配置的最简单方法(除了制作模块 @Global() 之外)是制作一个包装器模块,re-exports 配置后成为动态模块。

示例:假设我们有一个动态 FooModule,我们想要将 application 传递给它,以指定应用程序的名称,并且我们想要 re-use 中的那个模块其他几个地方

@Module({
  imports: [
    FooModule.forRoot(
      { application: 'Whosebug Dynamic Module Scope Question' }
    )
  ],
  exports: [FooModule],
})
export class FooWrapperModule {}

现在不再在多个地方再次导入 FooModule.forRoot(),我们只需导入 FooWrapperModule 并获得与最初传递的配置相同的 FooService 实例。

我确实想提一下,按照惯例,DynamicModule.forRoot/Async() usually 意味着在 RootModuleusually 在某处附加了 @Global()isGlobal: true 配置。情况并非总是如此,但相对来说是正确的。

DynamicModule.register/Async()另一方面,通常意味着我们正在为这个模块配置一个动态模块并且它可以在其他地方重新配置以拥有自己的单独配置。 This can lead to cool setups where you can have multiple JwtService instances that have different secret values for signing (like for an access and refresh token signing service).

然后是 DynamicModule.forFeature(),它类似于 register,因为它是基于每个模块的,但是 通常 它使用来自 [=28] 的配置=] 已经进行的调用。 @nestjs/typeorm module, mikro-orm/nestjs module, and @ogma/nestjs-module 模块是我能想到的遵循这种模式的三个独立示例。这是允许在根级别进行一般配置(应用程序名称、数据库连接选项等)然后允许在模块级别进行范围配置(将注入哪些实体、记录器上下文等)的好方法