😺

Nest.js におけるモジュール/サービス

2022/03/21に公開

Module のデコレータ

import { Module } from '@nestjs/common';
import {SendgridService} from "./sendgrid.service";

@Module({
    // モジュール定義をこちらに
})
export class HogeModule {
}
  • providers モジュール内で有効化するサービスを定義します。
  • controllers モジュール内で有効化する コントローラを定義します。
  • imports 読み込む外部のモジュールを定義します。
  • exports モジュールとして読み込まれた際に公開する サービスを定義します。

Angular のモジュールでは export を利用してコンポーネントやディレクティブの公開を行っていましたが、
nest.js における imports / exports は、主に Service の受け渡しをする目的で利用されます。

Service の Provider Scope

Nest.js には Angular のような injectedIn: "root" のような Provider Scope が存在せず、
すべてのモジュールは、モジュールの範囲でシングルトンで管理されます。

サーバサイドのスコープは、nest start でサーバを立ち上げたタイミングで処理され、
その後の各リクエスト内で同じオブジェクトが使い回されるため、
PHP などの shared nothing な バックエンド開発に慣れている人には注意が必要です。

Nest.js では、以下 3種の Scope が用意されています。

  • DEFAULT : オブジェクトはアプリケーション全体でシングルトンで管理されます。
  • REQUEST : オブジェクトはリクエストのたびに再生成され、破棄されます。
  • TRANSIENT : オブジェクトはユーザごとに生成され、同じユーザに同じオブジェクトが維持されます。

これらの Scope は以下のように injectable デコレータで定義することが可能です。

import { Injectable, Scope } from '@nestjs/common';

@Injectable({ scope: Scope.REQUEST })
export class CatsService {}

Controller ももちろん DI で管理されるオブジェクトです。
Controller の場合には、 controller ディレクティブ内で、 scope 値を利用して Scope を定義できます。

@Controller({
  path: 'cats',
  scope: Scope.REQUEST,
})
export class CatsController {}

Scope の階層化

Scope はの仕組みは、依存チェーンの中でバブリングします。

例えば、CatsController <- CatsService <- CatsRepositoryのような依存グラフがあり、
CatsService が RequestScope の場合、CatsController も RequestScope になります。

参考

https://docs.nestjs.com/modules

https://docs.nestjs.com/providers

https://docs.nestjs.com/fundamentals/injection-scopes

Discussion