Module

規範作用域

module 生成後元數據是空的,可以自己填入以下選項:

  • controllers:註冊 controller 元件
  • providers:註冊可以被注入的 service、repository 等元件
  • exports:將 provider 匯出,供其他 module 使用
  • imports:匯入其他 module,匯入後就能使用其他 module 中 exports 裡列出的 provider
@Module({
  controllers: [TodoController],
  providers: [TodoService],
  exports: [TodoService],
  imports: [UserModule],
})
export class TodoModule {}

module 會規範好作用域,controllersproviders 只能填入該模組下的元件,否則會因為無法找到正確的依賴而報錯。

imports / exports

將 module 中以 @Injectable 標記的元件匯出,如 service 或是自訂的 provider 邏輯,在其他模組就可以用 imports 匯入。

// 將 CopyService 填入 CopyModule 的 exports
@Module({
  //...
  exports: [CopyService],
})
export class CopyModule {}

// 在 TodoModule 的 imports 載入 CopyModule
@Module({
  //...
  imports: [CopyModule],
})
export class TodoModule {}

如果其中一邊忘了做匯入或匯出,在元件中注入時會報錯:

// 這個 import 匯入類別的定義
import { CopyService } from 'src/copy/copy.service';

// NestJS 用 CopyService 這個標記去尋找依賴注入容器中的實例時會報錯
// 因為沒有在各自的 @Module 中定義 imports 或 exports
@Controller('todos')
export class TodoController {
  constructor(private readonly copyService: CopyService) {}

  @Get('copy')
  getCopy() {
    return this.copyService.getCopy();
  }
}

常用模組

經常同時出現、互相綁定的模組,可以聚合成一包常用模組 (common module) 一起匯出:

@Module({
  imports: [TodoModule, CopyModule],
  exports: [TodoModule, CopyModule],
})
export class CommonModule {}

全域模組

@Module 前加入 @Global(),就會被標記成全域模組。

在根模組匯入之後,其他模組就可以跳過匯入的步驟:

@Global()
@Module({
  imports: [TodoModule, CopyModule],
  exports: [TodoModule, CopyModule],
})
export class CommonModule {}
// 在根模組匯入
@Module({
  controllers: [AppController, TodoController],
  providers: [AppService],
  imports: [TestModule, CommonModule],
})
export class AppModule {}
import { Module } from '@nestjs/common';
import { TestController } from './test.controller';

@Module({
  controllers: [TestController],
  // 不用寫 imports
})
export class TestModule {}

依賴注入後就可以成功呼叫:

import { Controller, Get } from '@nestjs/common';
import { TodoService } from 'src/todo/todo.service';

@Controller('test')
export class TestController {
  constructor(private readonly todoService: TodoService) {}

  @Get()
  getTest() {
    return this.todoService.getTodos();
  }
}
警告

大量使用的話也會有耦合的問題。


小結

module 元件主要是限制該資料夾下所有元件的作用域,由 importsexports 來決定 module 可以存取的元件。


參考資料