8
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Modules | NestJS 【翻訳】

Last updated at Posted at 2019-11-06

NestJS公式ドキュメント翻訳

NestJS公式ドキュメント翻訳

原文

Modules | NestJS - A progressive Node.js web framework

モジュール

モジュールは@Module()デコレータが付けられたクラスです。@Module()デコレータはNestがアプリケーション構造を整理するために使用するメタデータを提供します。

sf.PNG

各アプリケーションには少なくとも1つのモジュール、ルート(root)モジュールがあります。ルートモジュールはNestがアプリケーショングラフの構築の始点です。Nestはモジュールとプロバイダの関係と依存関係を解決するために使用する内部データ構造です。非常に小さなアプリケーションでは、理論的にはルートモジュールがありさえすればよいですが、これは一般的なケースではありません。コンポーネントを整理する効果的な方法としてモジュール化を強くお勧めします。ほとんどのアプリケーションではアーキテクチャは複数のモジュールを使用し、各モジュールは密接に関連する機能ごとにカプセル化します。

@Module()デコレータはプロパティがモジュールを記述する単一のオブジェクトを受け取ります

providers Nestインジェクタによってインスタンス化され、少なくともそのモジュール全体で共有されるプロバイダ
controllers インスタンス化する必要があるそのモジュールで定義されたコントローラのセット
imports そのモジュールで必要なプロバイダをエクスポートするインポートされたモジュールのリスト
exports そのモジュールによって提供され、そのモジュールをインポートする他のモジュールで利用できるprovidersのサブセット

モジュールはデフォルトでプロバイダをカプセル化します。これは、現在のモジュールの直接的な一部ではなく、インポートされたモジュールからエクスポートされていないプロバイダを注入することは不可能であることを意味します。したがって、モジュールからエクスポートされたプロバイダは、モジュールのパブリックインターフェースまたはAPIと見なすことができます。

機能モジュール

CatsControllerCatsServiceは同じアプリケーションドメインに属します。これらは密接に関連しているため、機能モジュールに移動することは理にかなっています。機能モジュールは特定の機能に関連するコードを整理し明確な境界を確立します。これにより、アプリケーションやチームの規模が大きくなっても、複雑性を管理しつつSOLIDの原則に従って開発することができます。

これを実証するために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を使用してモジュールを作成するには、単に$nest g module catsコマンドを実行します。

上記では、cats.module.tsファイルでCatsModuleを定義し、このモジュールに関連するすべてのものをcatsディレクトリに移動しました。最後に、このモジュールをルートモジュール(app.module.tsファイルで定義されているAppModule)にインポートします。

app.module.ts
import { Module } from '@nestjs/common';
import { CatsModule } from './cats/cats.module';

@Module({
  imports: [CatsModule],
})
export class AppModule {}

ディレクトリ構造は次のようになります。

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ではモジュールはデフォルトでシングルトンなので、複数のモジュール間で任意のプロバイダの同じインスタンスを簡単に共有することができます。

キャプチャf.PNG

すべてのモジュールは自動的に共有モジュールです。作成すると任意のモジュールで再利用できます。CatsServiceのインスタンスを他のいくつかのモジュール間で共有したいとします。これを行うには、最初にCatsServiceプロバイダをモジュールのexports配列に追加して、以下のようにエクスポートする必要があります。

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 {}

これでCatsModuleをインポートするモジュールはCatsServiceにアクセスでき、同じインスタンスをそれをインポートする他のすべてのモジュールで共有します。

モジュールの再エクスポート

上記のように、モジュールは内部プロバイダをエクスポートできます。さらに、インポートしたモジュールを再エクスポートできます。次の例では、CommonModuleCoreModuleにインポートおよびエクスポートされるため、このモジュールをインポートする他のモジュールで使用できます。

@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) {}
}

ただし、循環依存となるためモジュールクラス自体をプロバイダとして注入することはできません。

グローバルモジュール

どこにでも同じモジュールのセットをインポートする場合、冗長になる可能性があります。 Nestとは異なり、Angularprovidersはグローバルスコープに登録されます。定義すればどこでも利用できます。しかし、Nestはプロバイダをモジュールスコープ内にカプセル化します。最初にカプセル化したモジュールをインポートしないと、モジュールのプロバイダを他の場所で使用することはできません。

すぐに使用できるプロバイダのセット(ヘルパー、データベース接続など)を提供する場合は、@Global()デコレータを使用してモジュールをグローバルにします。

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()デコレータはモジュールをグローバルスコープにします。グローバルモジュールは、通常はルートモジュールまたはコアモジュールによって一度だけ登録する必要があります。上記の例では、CatsServiceプロバイダはどこにでもあり、サービスを注入したいモジュールはimports配列にCatsModuleをインポートする必要はありません。

すべてをグローバルにすることは設計上よくありません。必要なボイラープレートを減らすために、グローバルモジュールを使用しましょう。imports配列はモジュールのAPIを使う側が利用できるようにするための方法です。

動的モジュール

Nestモジュールシステムには、動的モジュールと呼ばれる強力な機能が含まれています。この機能により、プロバイダを動的に登録および構成するカスタマイズ可能なモジュールを簡単に作成できます。動的モジュールについてはここで詳しく説明します。この章では簡単な概要を示します。

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を介して)返します。

このモジュールは@Module()デコレータメタデータでConnectionプロバイダを定義しますが、さらに(forRoot()メソッドに渡されるentitiesoptionsオブジェクトに応じて)リポジトリなどのプロバイダのコレクションを公開します。動的モジュールによって返されるプロパティは@Module()デコレータで定義されたベースモジュールメタデータを(オーバーライドするのではなく)拡張することに注意してください。これが、静的に宣言されたConnectionプロバイダ動的に生成されたリポジトリプロバイダの両方をモジュールからエクスポートする方法です。

上記のように定義されると、DatabaseModuleは次の方法でインポートおよび構成されます。

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 {}

動的モジュールを順番に再エクスポートする場合、exports配列ではforRoot()メソッド呼び出しを省略できます。

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 {}

動的モジュールの章では、このトピックをより詳細に説明し実例を紹介します。

8
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?