模塊是具有 @Module() 裝飾器的類。 @Module() 裝飾器提供了元數(shù)據(jù),Nest 用它來組織應(yīng)用程序結(jié)構(gòu)。
每個 Nest 應(yīng)用程序至少有一個模塊,即根模塊。根模塊是 Nest 開始安排應(yīng)用程序樹的地方。事實上,根模塊可能是應(yīng)用程序中唯一的模塊,特別是當(dāng)應(yīng)用程序很小時,但是對于大型程序來說這是沒有意義的。在大多數(shù)情況下,您將擁有多個模塊,每個模塊都有一組緊密相關(guān)的功能。
@module() 裝飾器接受一個描述模塊屬性的對象:
providers | 由 Nest 注入器實例化的提供者,并且可以至少在整個模塊中共享 |
controllers | 必須創(chuàng)建的一組控制器 |
imports | 導(dǎo)入模塊的列表,這些模塊導(dǎo)出了此模塊中所需提供者 |
exports | 由本模塊提供并應(yīng)在其他模塊中可用的提供者的子集。 |
默認情況下,該模塊封裝提供程序。這意味著無法注入既不是當(dāng)前模塊的直接組成部分,也不是從導(dǎo)入的模塊導(dǎo)出的提供程序。因此,您可以將從模塊導(dǎo)出的提供程序視為模塊的公共接口或API。
CatsController 和 CatsService 屬于同一個應(yīng)用程序域。 應(yīng)該考慮將它們移動到一個功能模塊下,即 CatsModule。
cats/cats.module.ts
import { Module } from '@nestjs/common';
import { CatsController } from './cats.controller';
import { CatsService } from './cats.service';
@Module({
controllers: [CatsController],
providers: [CatsService],
})
export class CatsModule {}
要使用 CLI 創(chuàng)建模塊,只需執(zhí)行 $ nest g module cats 命令。
我已經(jīng)創(chuàng)建了 cats.module.ts 文件,并把與這個模塊相關(guān)的所有東西都移到了 cats 目錄下。我們需要做的最后一件事是將這個模塊導(dǎo)入根模塊 (ApplicationModule)。
app.module.ts
import { Module } from '@nestjs/common';
import { CatsModule } from './cats/cats.module';
@Module({
imports: [CatsModule],
})
export class ApplicationModule {}
現(xiàn)在 Nest 知道除了 ApplicationModule 之外,注冊 CatsModule 也是非常重要的。 這就是我們現(xiàn)在的目錄結(jié)構(gòu):
src
├──cats
│ ├──dto
│ │ └──create-cat.dto.ts
│ ├──interfaces
│ │ └──cat.interface.ts
│ ├─cats.service.ts
│ ├─cats.controller.ts
│ └──cats.module.ts
├──app.module.ts
└──main.ts
在 Nest 中,默認情況下,模塊是單例,因此您可以輕松地在多個模塊之間共享同一個提供者實例。
實際上,每個模塊都是一個共享模塊。一旦創(chuàng)建就能被任意模塊重復(fù)使用。假設(shè)我們將在幾個模塊之間共享 CatsService 實例。 我們需要把 CatsService 放到 exports 數(shù)組中,如下所示:
cats.module.ts
import { Module } from '@nestjs/common';
import { CatsController } from './cats.controller';
import { CatsService } from './cats.service';
@Module({
controllers: [CatsController],
providers: [CatsService],
exports: [CatsService]
})
export class CatsModule {}
現(xiàn)在,每個導(dǎo)入 CatsModule 的模塊都可以訪問 CatsService ,并且它們將共享相同的 CatsService 實例。
模塊可以導(dǎo)出他們的內(nèi)部提供者。 而且,他們可以再導(dǎo)出自己導(dǎo)入的模塊。
@Module({
imports: [CommonModule],
exports: [CommonModule],
})
export class CoreModule {}
提供者也可以注入到模塊(類)中(例如,用于配置目的):
cats.module.ts
import { Module } from '@nestjs/common';
import { CatsController } from './cats.controller';
import { CatsService } from './cats.service';
@Module({
controllers: [CatsController],
providers: [CatsService],
})
export class CatsModule {
constructor(private readonly catsService: CatsService) {}
}
但是,由于循環(huán)依賴關(guān)系,模塊類不能注入到提供者中。
如果你不得不在任何地方導(dǎo)入相同的模塊,那可能很煩人。在 Angular 中,提供者是在全局范圍內(nèi)注冊的。一旦定義,他們到處可用。另一方面,Nest 將提供者封裝在模塊范圍內(nèi)。您無法在其他地方使用模塊的提供者而不導(dǎo)入他們。但是有時候,你可能只想提供一組隨時可用的東西 - 例如:helper,數(shù)據(jù)庫連接等等。這就是為什么你能夠使模塊成為全局模塊。
import { Module, Global } from '@nestjs/common';
import { CatsController } from './cats.controller';
import { CatsService } from './cats.service';
@Global()
@Module({
controllers: [CatsController],
providers: [CatsService],
exports: [CatsService],
})
export class CatsModule {}
@Global 裝飾器使模塊成為全局作用域。 全局模塊應(yīng)該只注冊一次,最好由根或核心模塊注冊。 在上面的例子中,CatsService 組件將無處不在,而想要使用 CatsService 的模塊則不需要在 imports 數(shù)組中導(dǎo)入 CatsModule。
使一切全局化并不是一個好的解決方案。 全局模塊可用于減少必要模板文件的數(shù)量。 imports 數(shù)組仍然是使模塊 API 透明的最佳方式。
Nest 模塊系統(tǒng)包括一個稱為動態(tài)模塊的強大功能。此功能使您可以輕松創(chuàng)建可自定義的模塊,這些模塊可以動態(tài)注冊和配置提供程序。動態(tài)模塊在這里廣泛介紹。
以下是一個動態(tài)模塊定義的示例 DatabaseModule:
import { Module, DynamicModule } from '@nestjs/common';
import { createDatabaseProviders } from './database.providers';
import { Connection } from './connection.provider';
@Module({
providers: [Connection],
})
export class DatabaseModule {
static forRoot(entities = [], options?): DynamicModule {
const providers = createDatabaseProviders(options, entities);
return {
module: DatabaseModule,
providers: providers,
exports: providers,
};
}
}
forRoot() 可以同步或異步(Promise)返回動態(tài)模塊。
此模塊 Connection 默認情況下(在 @Module() 裝飾器元數(shù)據(jù)中)定義提供程序,但此外-根據(jù)傳遞給方法的 entities 和 options 對象 forRoot() -公開提供程序的集合,例如存儲庫。請注意,動態(tài)模塊返回的屬性擴展(而不是覆蓋)@Module() 裝飾器中定義的基本模塊元數(shù)據(jù)。這就是從模塊導(dǎo)出靜態(tài)聲明的 Connection 提供程序和動態(tài)生成的存儲庫提供程序的方式。
如果要在全局范圍內(nèi)注冊動態(tài)模塊,請將 global 屬性設(shè)置為 true。
{
global: true,
module: DatabaseModule,
providers: providers,
exports: providers,
}
如上所述,將所有內(nèi)容全局化不是一個好的設(shè)計決策。
所述 DatabaseModule 可以被導(dǎo)入,并且被配置以下列方式:
import { Module } from '@nestjs/common';
import { DatabaseModule } from './database/database.module';
import { User } from './users/entities/user.entity';
@Module({
imports: [DatabaseModule.forRoot([User])],
})
export class AppModule {}
如果要依次重新導(dǎo)出動態(tài)模塊,則可以 forRoot() 在導(dǎo)出數(shù)組中省略方法調(diào)用:
import { Module } from '@nestjs/common';
import { DatabaseModule } from './database/database.module';
import { User } from './users/entities/user.entity';
@Module({
imports: [DatabaseModule.forRoot([User])],
exports: [DatabaseModule],
})
export class AppModule {}
更多建議: