Node.js バックエンド開発者であれば、デフォルトでは Node.js が非常に必要最低限の機能を備えており、アプリの構築中に何が必要かを想定していないことに同意するでしょう。その結果、ルーティングの処理、API 呼び出しの実行、TypeScript や Web ソケットのセットアップ、さらにはコード構成、ファイル構造、命名規則などの基本的な事項まで、アプリ全体で使用するすべての設定を担当することになります。 。
大規模なアプリケーションの管理は、特に明確な構造と厳格なコード編成ガイドラインに従って設計されていない場合には、困難な作業になる可能性があります。
Nest.js は、開発者が他の小さな実装の詳細ではなくアプリケーションの問題に集中できるように、Node.js の周囲に抽象化を作成することで、これらの問題のいくつかに対処しようとします。
このガイドでは、Nest.js の核となる基礎を上から下まで学習し、Nest.js を利用してエンタープライズ グレードの Node.js アプリケーションをすぐに構築できるようにすることを目的としています。
このガイドを通じて私たちが学ぶことはすべて段階的に行われます。入門概念に関する多くの内容をカバーしています。このガイドを最大限に活用するには、コードに沿ってコーディングすることが役立ちます。
早速始めましょう、皆さん!
ソースコード: いつものように、でホストされているソース コードをフォークしていじることができます。 GitHubの.
注: Postman を使用して、デモで API をテストします。 でダウンロードできます。 ポストマンのダウンロードページ. または、単にブラウザのコマンドラインを使用することもできます curl
ツール、または使い慣れたその他のツールを使用できます。
Nest.jsとは
Nest.js は、難しいタスク、ツール、定型コードを抽象化すると同時に、最新の JavaScript と TypeScript を使用したアプリケーション開発のための本格的なツールキットを追加する Node.js のスーパーセットと考えてください。
Nest.js は、すぐに使用できるアプリケーション アーキテクチャを提供します。これにより、開発者やチームは、コミュニティですぐに利用できる著名なオプションやモジュールを活用することで、拡張性が高く、テスト可能で、疎結合で、保守が容易な製品を作成できます。 Express.js アプリケーション。 Express (デフォルトで内部で使用されます) を Fastify に交換することもできますが、その場合、アプリケーションで別の Fastify 準拠ライブラリを使用する必要がある可能性があります。
関数型プログラミング、オブジェクト指向プログラミング、関数型リアクティブ プログラミングの機能を組み合わせており、52.4k 個を超えるスターと 6.2k 個のフォークを備えています。 GitHubの 毎週のダウンロード数が最大 1,784,004 に達する進歩的な Node.js フレームワークは、効率的でスケーラブルなエンタープライズ グレードのサーバー側アプリケーションを作成するための人気の頼りになります。
Nest.jsの特徴
Nest.js がこれほど人気のある Node.js フレームワークに成長した理由は次のとおりです。
- Nest.js は、開発者がモノリシック アプリケーションとマイクロサービスの両方を構築できるようにするために作成されました。
- これは強力であると同時に、開発者にとって使いやすいものでもあります。使いやすく、すぐに習得でき、簡単に適用できます。
- TypeScript (JavaScript のスーパーセット) をそのまま利用し、開発者が実行時エラーのない保守可能なコードを作成できるようにします。
- 開発者の生産性を向上させ、開発を容易にするコマンド ライン インターフェイスを備えています。
- Nest.js を使用して構築すると、Nest にはデフォルトで素晴らしいプロジェクト フォルダー構造が付属しているため、Minimum Viable Product をブートストラップしている場合でも、アプリケーションで作業している場合でも、開発プロセスが強化され、時間が節約されます。
- TypeORM、GraphQL、ロギング、検証、Mongoose、WebSocket、キャッシュなどの共通の概念とテクノロジーの統合に役立つさまざまな Nest 固有のモジュールをサポートしています。
- Nest.js は、あらゆるフレームワークに関する最高のドキュメントを保持していることを誇りに思っています。そのドキュメントは徹底的で理解しやすく、問題の解決策が必要なときに簡単に理解できるため、デバッグ時間の節約に役立ちます。
- Nest.js は Jest と統合されているため、アプリケーションで単体テストを簡単に作成できます。
- これは、小規模と大規模の両方のエンタープライズ アプリケーション向けに構築されています。
Nest.js プロジェクトの作成
ローカルマシンで Nest.js を使い始めるには、まず Nest コマンドライン インターフェイス (CLI) をインストールする必要があります。これは、新しい Nest.js プロジェクト フォルダーを足場にして、そのフォルダーに必要なコア ファイルとモジュールを追加するのに役立ちます。 Nest.js アプリケーション。
次のコマンドを実行して、Nest.js コマンドライン インターフェイスをインストールします。
$ npm i -g @nestjs/cli
// Or
$ yarn global add @nestjs/cli
// Or
$ pnpm add -g @nestjs/cli
Nest.js CLI をローカル マシンにグローバルに正常にインストールしたら、次のコマンドを実行できます。 nest
コマンドラインで、利用できるさまざまなコマンドを確認します。
$ nest
での結果:
Usage: nest [options]
Options:
-v, --version Output the current version.
-h, --help Output usage information.
Commands:
new|n [options] [name] Generate Nest application.
build [options] [app] Build Nest application.
start [options] [app] Run Nest application.
info|i Display Nest project details.
add [options] Adds support for an external library to your project.
generate|g [options] [name] [path] Generate a Nest element.
Schematics available on @nestjs/schematics collection:
┌───────────────┬─────────────┬──────────────────────────────────────────────┐
│ name │ alias │ description │
│ application │ application │ Generate a new application workspace │
│ class │ cl │ Generate a new class │
│ configuration │ config │ Generate a CLI configuration file │
│ controller │ co │ Generate a controller declaration │
│ decorator │ d │ Generate a custom decorator │
│ filter │ f │ Generate a filter declaration │
│ gateway │ ga │ Generate a gateway declaration │
│ guard │ gu │ Generate a guard declaration │
│ interceptor │ itc │ Generate an interceptor declaration │
│ interface │ itf │ Generate an interface │
│ middleware │ mi │ Generate a middleware declaration │
│ module │ mo │ Generate a module declaration │
│ pipe │ pi │ Generate a pipe declaration │
│ provider │ pr │ Generate a provider declaration │
│ resolver │ r │ Generate a GraphQL resolver declaration │
│ service │ s │ Generate a service declaration │
│ library │ lib │ Generate a new library within a monorepo │
│ sub-app │ app │ Generate a new application within a monorepo │
│ resource │ res │ Generate a new CRUD resource │
└───────────────┴─────────────┴──────────────────────────────────────────────┘
ここでは、コマンドの使用方法が示されており、次のコマンドを利用できるようになります。 new|n [options] [name]
最初の Nest.js プロジェクトを作成するコマンド:
$ nest new getting-started-with-nestjs
// Or
$ nest n getting-started-with-nestjs
次に、どのパッケージ マネージャーを使用するかを尋ねられます。
? Which package manager would you ❤️ to use? (Use arrow keys)
npm
yarn
> pnpm
好みのパッケージ マネージャーを自由に選択してください。私はこれを使用します。 pnpm
。これは、NPM よりも約 3 倍効率的かつ高速であり、高速なキャッシュ システムを備えているため、PNPM も Yarn よりも高速であるためです。
パッケージ マネージャーを選択した後、インストール プロセスが続行され、Nest.js アプリが作成されます。
さて、次のことができます cd
新しく作成したプロジェクトに追加し、選択したエディターで開きます。
$ cd getting-started-with-nestjs
プロジェクトが作成されたので、次のコマンドのいずれかを使用して実行できます。
$ npm run start
// Or
$ yarn start
// Or
$ pnpm run start
あなたが見てみると package.json
ファイルのスクリプト セグメントに、次の値があることがわかります。 pnpm run start
is nest start
:
"start": "nest start",
つまり、次のコマンドを実行して Nest.js アプリを実行することもできます。
$ nest start
Nest.js プロジェクト構造の概要
Nest アプリの構造を詳しく見てみましょう。
/package.json
package.json
ファイルは Node.js の中心部であり、拡張子として Nest.js プロジェクトとなります。これはプロジェクトに関するすべてのメタデータを保持し、アプリケーションの依存関係をインストールしたりプロジェクト スクリプトを実行したりするために必要なプロジェクトのさまざまな機能プロパティを定義します。
私たちはすでにその能力を見てきました。 start
スクリプト。
start:dev
プロファイルを使用すると、アプリケーションを停止して再起動することなく、アプリケーションの変更を監視し、自動的にリロードすることができます。これは開発向けです。の start:prod
このスクリプトは、Nest.js アプリをテストするための他のスクリプトと同様に、アプリケーションが本番環境に対応しているかどうかをテストする場合や、アプリケーションを本番環境にデプロイする場合に役立ちます。
@nestjs/platform-express
Express を Nest アプリケーションのデフォルトの HTTP サーバーとして定義します。
/tsconfig.json
tsconfig.json
ファイルは、Nest アプリのコンパイルに必要な TypeScript 関連のオプションを定義する JSON (JavaScript Object Notation) で記述されたファイルです。
/nest-cli.json
これには、Nest アプリケーションを構築、整理、デプロイするために必要なメタデータが保持されます。
/test
このディレクトリには、Nest テストの実行に必要なすべてのファイルが保存されます。 Nest は、Jest 構成でのテストに Jest フレームワークを使用します。 jest-e2e.json
ファイルにソフトウェアを指定する必要があります。
/src
src
directory は、Nest プロジェクトのコアの親フォルダーです。それは、 main.ts
ファイルは、Nest アプリが起動するファイルです。の仕事 main.ts
ファイルがロードされます AppModule
それはから輸入されています /src/app.module.ts
.
このガイドの後半では、モジュールについて学びます。 Nest.js アプリケーションの主要コンポーネントの 1 つ。
AppModule
を使用してモジュールとして作成されるクラスです。 @Module
デコレーター。の中に app.module.ts
ファイル、 AppService
から ./app.service
および AppController
から ./app.controller
も輸入されています。
AppController
を使用して作成されるクラスでもあります。 @Controller
デコレータ、一方 AppService
を使用して作成されたクラスです。 @Injectable
注釈。
Nest の優れた点は、クラスにメタデータを追加するデコレータがほとんどなく、そのメタデータがそのクラスの目的を次のように定義することです。
@Controller()
クラスをコントローラーに変換します。@Module()
クラスをモジュールに変換します。@Injectable()
クラスをプロバイダーに変換します。
にも src
ディレクトリは app.controller.spec.ts
ファイルは、コントローラーのテスト ファイルです。
次を使用してアプリを実行できます nest start
.
アプリは次の時点で開始されます http://localhost:3000
ブラウザ上で:
に表示されるコンテンツを変更できます。 http://localhost:3000
に向かうことで、 app.service.ts
ファイル。インデックス ルートのプロバイダーが定義されています。
Nest.js アプリの構成要素
Nest.js アプリケーションには 3 つの主要コンポーネントがあります。
- モジュール
- コントローラ
- プロバイダ
Nest アプリの構成要素について学習するには、まず Nest プロジェクトを削除してクリーンアップしましょう。 app.controller.spec.ts
, ./app.service
, app.module.ts
, ./app.controller
ファイル。ただ出発する main.ts
、最初からの開発ライフサイクルをエミュレートします。
この時点で、インポートされたファイルを削除すると、 AppModule
からのファイル main.ts
とすると、「モジュール」の引数が指定されていないというメッセージが表示されます。
Nest アプリの構成要素を示すために、オブジェクトに対する CRUD 操作を処理する REST API を構築することにより、単純なユーザー プロファイルの実装を見ていきます。
モジュール
src
フォルダーを新規作成する app.module.ts
ファイルを作成してから、 AppModule
クラスをエクスポートします。
次に、をインポートします AppModule
にクラス分けする main.ts
、実行 nest start
.
MFAデバイスに移動する http://localhost:3000
ブラウザで実行すると、404 エラーが発生します。
これは、Nest アプリのベース URL のルートをまだ定義していないためです。
後ろに app.module.ts
、私たちは AppModule
私たちが持っているクラスはまだNestモジュールではありません。これを Nest モジュールにするには、次のように追加します。 @Module()
からインポートされたデコレータ @nestjs/common
次に、空のオブジェクトを渡します。
import { Module } from '@nestjs/common';
@Module({})
export class AppModule {}
これで、Nest.js モジュールが完成しました。
注: モジュールは、アノテーションが付けられたクラスです。 @Module()
デコレータ。
すべての Nest アプリケーションにはルート モジュールがあり、Nest アプリケーションの構造と関係を解決するためのエントリ ポイントとして機能します。
複数のモジュールを使用してアプリケーションのコンポーネントを整理することを強くお勧めします。
@Module()
デコレータを使用すると、開発者が Nest アプリのクラスに関するメタデータを定義できるようになります。
ユーザー モジュール、注文モジュール、チャット モジュールなど、複数のモジュールがある場合、 app.module.ts
Nest アプリの他のすべてのモジュールを登録するために使用する必要があります。
ルートの作成;コントローラー
Nest アプリケーションでルートを作成するにはコントローラーが必要です。コントローラーの目的は、Nest アプリケーションに対する特定のリクエストを受信することです。アプリケーション内のさまざまなルートの要求と応答のサイクルを制御します。
クライアントから Nest アプリケーションに対して HTTP リクエストが行われると、リクエストが行われたルートと一致するルートがリクエストを処理し、適切な応答を返します。
Nest アプリでコントローラーを作成するには、 @Controller()
デコレータ。
src
ディレクトリに新しいファイルを作成します app.contoller.ts
その中で、Nest コントローラーを定義できます。
import { Controller } from '@nestjs/common';
@Controller({})
export class AppController {}
それだ!非常に優れたコントローラーができましたが、新しいルートを作成するには、まず作成したコントローラーについて Nest アプリに知らせる必要があります。
これを達成するために、必ずインポートします AppController
app.module.ts にコントローラーに関する情報を定義します。 @Module()
デコレーター – コントローラーの配列として:
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
@Module({
controllers: [AppController],
})
export class AppModule {}
GETリクエストの処理
次に、単純な関数を定義します。 getUser()
ルート( @Get()
指定されたパスへの HTTP GET リクエストを処理するために使用されるデコレータ) がベース ルートとして機能するため、ブラウザ上で同じものにアクセスできます。 https://localhost:3000
:
import { Controller, Get } from '@nestjs/common';
@Controller({})
export class AppController {
@Get()
getUser() {
return 'I am a great person';
}
}
この結果:
うーん、ここでは文字列だけを返していますが、オブジェクトを返したい場合はどうすればよいでしょうか?文字列の代わりにオブジェクトを定義できます。
import { Controller, Get } from '@nestjs/common';
@Controller({})
export class AppController {
@Get()
getUser() {
return { name: 'Uchechukwu Azubuko', country: 'Nigeria' };
}
}
MFAデバイスに移動する http://localhost:3000
ブラウザに次のオブジェクトが表示されます。
基本ルートから離れて、次のようなルートを作成してみてはいかがでしょうか http://localhost:3000/user
すべてのユーザーを取得するには?
このようなルートを処理するコントローラーをいくつかの方法で作成できます。
1 つの方法は、次のメソッドを使用して新しいメソッドを定義することです。 @Get()
デコレータ/ハンドラ。
import { Controller, Get } from '@nestjs/common';
@Controller({})
export class AppController {
@Get()
getUser() {
return { name: 'Uchechukwu Azubuko', country: 'Nigeria' };
}
}
Nest.js は、さまざまな HTTP メソッドすべてにデコレータまたはハンドラを提供します。 @Get()
, @Post()
, @Put()
, @Delete()
, @Patch()
, @Options()
, @Head()
.
@All()
デコレーターは、さまざまなメソッドをすべて処理するエンドポイントを定義します。
POSTリクエストの処理
また、データベースにデータを保存するための POST リクエストを定義することもできます。 @Post()
デコレータ:
import { Controller, Post } from '@nestjs/common';
@Controller({})
export class AppController {
@Post()
store() {
return 'Post request successful';
}
}
次に、Postman を使用して POST リクエストをテストすると、文字列が定義どおりに正常に返されることがわかります。
データを返す以外のことも行いたい場合はどうすればよいのかと疑問に思われるかもしれません。おそらく、データを送信するためです。
そのためには、次に示すように、ルート メソッド内にデータを挿入する必要があります。
import { Controller, Post, Req } from '@nestjs/common';
import { Request } from 'express';
@Controller({})
export class AppController {
@Post()
store(@Req() req: Request) {
return req.body;
}
}
Postman を使用して POST リクエストをテストすると、送信されているデータを表示できるようになりました。この場合、それは単なる空のオブジェクトです。
ベストプラクティス、業界で認められた標準、および含まれているチートシートを含む、Gitを学習するための実践的で実用的なガイドを確認してください。 グーグルGitコマンドを停止し、実際に 学ぶ それ!
ルートパラメータを使用した動的ルーティング
リクエストの一部として動的データを受け入れたいとします。まず、ルート/URL 上の動的な位置を記録するために、ルートのパスにトークンを定義する必要があります。次に、 @Param()
デコレータでは、次のようにルート パラメータにアクセスできます。
import { Controller, Get, Param } from '@nestjs/common';
@Controller({})
export class AppController {
@Get('/:userId')
getUser(@Param() userId: number) {
return userId;
}
}
userId
は正常に返されます:
非同期リクエストの処理
Nest.js は、さまざまなアプローチを使用して Promise を返す非同期リクエストを処理できます。
import { Controller, Get} from '@nestjs/common';
@Controller({})
export class AppController {
@Get()
async findAll(): Promise {
return [];
}
}
上記のアプローチでは、非同期性は次を使用して処理されます。 async
キーワード。もう 1 つのアプローチは、RxJS の監視可能なストリームを返すことです。
import { Controller, Get} from '@nestjs/common';
@Controller({})
export class AppController {
@Get()
findAll(): Observable {
return of([]);
}
}
ここで、Nest.js は内部でソースをサブスクライブし、ストリームが完了すると、最後に出力された値を自動的に取得します。
Nest でのリダイレクトの処理
@Redirect()
デコレータは、応答を別の URL にリダイレクトするために使用されます。の @Redirect()
デコレーターは 2 つの引数を受け入れます。リダイレクト先の URL とリダイレクト時のステータス コードです。どちらもオプションです。
import { Controller, Get} from '@nestjs/common';
@Controller({})
export class AppController {
@Get()
@Redirect('https://www.ucheazubuko.com', 302)
getSite() {
return { url: 'https://stackabuse.com' };
}
}
ステータスコードを返す
Nest.js サーバーで処理されたリクエストのステータス コードを返すには、 @HttpCode(…)
簡単に通り抜けます。
Nest では、GET リクエストのデフォルトのステータス コードは 200、POST リクエストは 201、エラー リクエストは 304 です。
サーバー リクエストのステータス コードは次のように定義できます。
import { Controller, Post, HttpCode } from '@nestjs/common';
@Controller({})
export class AppController {
@Post()
@HttpCode(204)
create() {
return 'This action adds a new user to the app.';
}
}
DELETE リクエストの処理
POST リクエストの作成と同様に、削除リクエストは次のように処理できます。
import { Controller, Delete, Param } from '@nestjs/common';
@Controller({})
export class AppController {
@Delete('/:userId')
delete(@Param() params: { userId: number }) {
return params;
}
}
UPDATEリクエストの処理
サーバー上の特定のデータを更新するリクエストは、 @Patch()
デコレータ:
import { Controller, Patch, Req} from '@nestjs/common';
import { Request } from 'express';
@Controller({})
export class AppController {
@Patch('/:userId')
update(@Req() req: Request) {
return req.body;
}
}
堅牢なサーバー上によくある典型的なコントローラーを定義するさまざまな方法を見てきましたが、コントローラーは無駄がなく、クリーンで、定義する別のコントローラーがある場合など、ユースケースごとに定義される必要があることに注意することが重要です。 user
ルートを作成する場合は、別のディレクトリを作成し、同じ処理専用のディレクトリを、ルートから離れた場所に作成する必要があります。 AppController
.
それで user.controller.ts
、その中のすべてのルート ハンドラーにプレフィックスが付くように構成できます。 /user/
以下に示すようなコードを記述します。
import { Controller, Get } from '@nestjs/common';
@Controller('/user')
export class UserController {
@Get()
getUser() {
return 'I am from the user controller';
}
}
次に登録します UserController
コントローラの配列内 app.modules.ts
:
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { UserController } from './controllers/user/user.controller';
@Module({
controllers: [AppController, UserController],
})
export class AppModule {}
に移動すると、 https:localhost:3000/user
、正常に返されます。
プロジェクト フォルダーを現在よりもさらに整理した状態に保つために、 user.module.ts
ファイルを定義します。 UserController
:
import { Module } from '@nestjs/common';
import { UserController } from './user.controller';
@Module({
controllers: [UserController],
})
export class UserModule {}
次に、インポートします UserModule
に app.module.ts
:
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { UserModule } from './user/user.module';
@Module({
controllers: [AppController],
imports: [UserModule],
})
export class AppModule {}
これで先ほどと同じ効果が得られます。
注: Nest を使用すると、モジュールとコントローラーを簡単に生成できます。 nest g mo
および nest g co
コマンド。特定のモジュール、 user
モジュールとコントローラは、Nest CLI を使用して次のコマンドを実行して迅速に作成することもできます。 nest g mo user
– ユーザーモジュールを作成するため、および nest g co user
– ユーザー コントローラーを作成します。
プロバイダ
データベースからのすべてのデータの取得は、ユーザー向けコードと潜在的に機密データと対話するコードの間に抽象化レイヤーを作成するために、コントローラーではなくプロバイダーによって処理される必要があります。これらの層の間では、適切なデータベース処理を保証するために検証を設定できます。 Nest CLI を使用すると、サービスを生成してプロバイダーを作成できます。
$ nest g s user
これにより、 UserService
ここで、すべてのビジネス ロジックを定義します。 UserController
ので、 UserController
リクエストとレスポンスのみを処理します。で user.service.ts
、次のことがわかります。 @Injectable()
デコレータはクラスを定義するために使用されます。 Nest では、 @Injectable()
デコレータは、サービス、リポジトリ、またはヘルパー クラスをプロバイダに変換します。
プロバイダーは、コンストラクターを通じてクラスに挿入されます。例を詳しく見てみましょう。
以前、 user.controller.ts
では、ユーザー オブジェクトを取得するためのビジネス ロジックを定義しましたが、今度は同じものを UserService
:
import { Controller, Injectable } from '@nestjs/common';
@Controller({})
export class AppController {
@Injectable()
get() {
return { name: 'Uchechukwu Azubuko', country: 'Nigeria'; };
}
}
次に、 user.controller.ts
ファイルにコンストラクターを定義しましょう UserController
クラス。このコンストラクターでは、プライベート userService
の一種です。 UserService
クラス。このプライベートを使用することで、ユーザーを取得するために以前に定義したビジネス ロジックを利用できるようになります。
import { Controller, Get } from '@nestjs/common';
import { UserService } from './user.service';
@Controller('/user')
export class UserController {
constructor(private userService: UserService) {}
@Get()
getUser() {
return this.userService.get();
}
}
マルサス、 UserController
クラス、現在は UserService
として知られる概念のクラス
依存性注入。
同様に、両方のロジックは、 user.controller.ts
および user.service.ts
ファイルはそれに応じて更新されます。
import {
Controller,
Delete,
Get,
Param,
Patch,
Post,
Req,
} from '@nestjs/common';
import { Request } from 'express';
import { UserService } from './user.service';
@Controller('user')
export class UserController {
constructor(private userService: UserService) {}
@Get()
getUsers() {
return this.userService.get();
}
@Get('/:userId')
getUser(@Param() param: { userId: number }) {
return this.userService.getUser(param);
}
@Post()
store(@Req() req: Request) {
return this.userService.create(req);
}
@Patch('/:userId')
update(@Req() req: Request, @Param() param: { userId: number }) {
return this.userService.update(req, param);
}
@Delete()
delete(@Param() param: { userId: number }) {
return this.userService.delete(param);
}
}
import { Injectable } from '@nestjs/common';
import { Request } from 'express';
@Injectable()
export class UserService {
get() {
return { name: 'Uchechukwu Azubuko', country: 'Nigeria' };
}
getUser(param: { userId: number }) {
return param;
}
create(req: Request) {
return req.body;
}
update(req: Request, param: { userId: number }) {
return { body: req.body, param };
}
delete(param: { userId: number }) {
return param;
}
}
次に、Postman を使用して、エンドポイントが正常に動作することを確認してみましょう。
Nest.js での依存関係の注入をわかりやすく説明する
クラスやモジュールなど、アプリケーションのより小さなコンポーネントを構築する場合、クラスは別のクラスやモジュールの機能に依存する場合があります。たとえば、API 呼び出しを行うために別のクラスによって提供される HTTP サービスを利用する必要がある場合や、永続層と対話するサービス層。
依存関係はコントローラー内で提供できます。 依存性注入.
依存関係の注入は、高い凝集性と疎結合を実現する方法で、アプリケーションの一部を、それを必要とするアプリケーションの他の部分に配信する方法を表現するプログラミングの概念およびパターンです。
Nest は依存関係の挿入をサポートしており、Nest アプリケーションで依存関係の挿入を使用してプロジェクトのモジュール性を強化できます。
実際の図は次のように表されます。
クラス A がクラス B の機能を使用するとします。その場合、クラス A はクラス B に依存していると言われます。したがって、クラス A でクラス B を使用するには、まずクラス B のインスタンスを作成する必要があります (つまり、クラス B オブジェクト):
const b = new B ()
.
クラスのインスタンスを作成するタスクを別のクラスに転送し、提供されているクラス (インジェクター コンポーネント) の依存関係を直接使用することは、依存関係の注入として知られています。
アドバイス: 依存関係注入 (DI) は、Spring Boot、Nest.js、Angular.js などのフレームワークの基本概念の 1 つです。詳細については、 Angular の公式ドキュメント.
通常、クラスは、必要かどうかにかかわらずさまざまなオブジェクトを作成するために使用されるのではなく、その機能を果たすことだけに集中する必要があります。
依存関係の注入の利点。
- 単体テストに役立ちます。
- 依存関係の注入では、依存関係の初期化がインジェクター コンポーネントによって行われるため、定型コードが削減されます。
- アプリケーションを拡張するプロセスが簡単になります。
- 依存関係の注入は、疎結合を有効にするのに役立ちます。
リクエストペイロードの調査
POST や PATCH などのさまざまなリクエスト ハンドラーで、サーバーから送信されたリクエストを利用することができたことを思い出してください。 @Req()
デコレーター。ただし、それだけではありません。
リクエスト オブジェクト全体を取得するのではなく、リクエスト オブジェクトの必要な特定の部分だけを利用することができます。
したがって、Nest は、Fastify オブジェクトの Express にアクセスするために HTTP ルート ハンドラーで使用できるさまざまなデコレーターを提供します。
巣の装飾者 | アクセスされる Fastify または Express オブジェクト |
`@Request()、@Req()` | `要求` |
`@Response()、@Res()` | 「れ」 |
`@Next()` | 「次へ」 |
`@セッション()` | 「要求セッション」 |
`@Param(param?: string)` | `req.params` / `req.params[param]` |
`@Body(param?: string)` | `req.body` / `req.body[param]` |
`@Query(param?: string)` | `req.query` / `req.query[param]` |
`@Headers(param?: string)` | `req.headers` / `req.headers[param]` |
`@Ip()` | `req.ip` |
`@HostParam()` | 「req.hosts」 |
典型的な例としては、 @Req()
結果の本体にアクセスするために以前に使用したデコレータ。 @Body()
これにより、ドリルせずにリクエストの本文に直接アクセスできるようになります。
@Post()
store(@Body() body: any) {
return this.userService.create(body);
}
@Patch('/:userId')
update(@Body() body: any, @Param() param: { userId: number }) {
return this.userService.update(body, param);
}
create(body: any) {
return body;
}
update(body: any, param: { userId: number }) {
return { body: body, param };
}
場合によっては、リクエスト ペイロードの特定のプロパティのみを取得したい場合があります。その場合、データ転送オブジェクト (DTO) スキーマを定義する必要があります。データ転送スキーマは、取得されるオブジェクトのコピーを定義するオブジェクトですが、主に、保存または取得されるオブジェクトと永続層の間でデータを転送するために使用されます。通常、このプロセスは攻撃に対して脆弱であるため、DTO にはそれほど多くの機密データ ポイントが含まれません。この特性により、オブジェクトの特定のフィールドのみを取得することもできます。
Nest では、クラスの値がコンパイル中に保持されるため、クラスを使用してデータ転送オブジェクトを定義することをお勧めします。
リクエストの本文にトークンがあり、そのようなデータを取得または更新したくない場合は、DTO を次のように定義できます。
@Patch('/:userId')
update(
@Body() updateUserDto: { name: string; email: string },
@Param() param: { userId: number },
) {
return this.userService.update(updateUserDto, param);
}
update(
updateUserDto: { name: string; email: string },
param: { userId: number },
) {
return { body: updateUserDto, param };
}
ただし、次のタイプを定義していることに気づくでしょう。 updateUserDto
2回。で user.service.ts
または user.controller.ts
, ただし、コードベースの周りで同じことを繰り返さないように、コードを DRY (Don'trepeat Yourself) に保つ必要があります。
このために、新しいフォルダーに /user/dto
セクションに /user
ディレクトリにあるファイルを作成する必要があります /update-user.dto.ts
.dto.ts
拡張子を定義してエクスポートします。 UpdateUserDto
で使用するクラス user.service.ts
および user.controller.ts
ファイル:
export class UpdateUserDto {
name: string;
email: string;
}
...
import { UpdateUserDto } from './dto/update-user.dto';
@Patch('/:userId')
update(
@Body() updateUserDto: UpdateUserDto,
@Param() param: { userId: number },
) {
return this.userService.update(updateUserDto, param);
}
...
import { UpdateUserDto } from './dto/update-user.dto';
update(updateUserDto: UpdateUserDto, param: { userId: number }) {
return { body: updateUserDto, param };
}
パイプと検証
サーバー経由でリクエストが行われたときに取得したデータを検証する必要があるとします。
Nest では、2 つの依存関係をインストールするパイプを使用して、アプリケーションに出入りするデータの正確さをテストできます。 class-validator
および class-transformer
.
パイプは、次のように定義されるクラスです。
@Injectable()
デコレーター (したがって、パイプはプロバイダーです)。PipeTransform
インターフェース。データを目的の形式に変換し、データが有効であると判断された場合は変更せずに渡し、そうでない場合は例外がスローされるようにデータを評価します。パイプを使用するには、特定のパイプ クラスのインスタンスを適切なコンテキストにバインドする必要があります。
class-validator
パッケージを使用すると、デコレータと非デコレータを検証できるようになります。 バリデーター.js 内部的に。一方、 class-transformer
package を使用すると、オブジェクトをクラスのインスタンスに変換したり、クラスをオブジェクトに変換したり、特定の基準に基づいてオブジェクトをシリアル化または逆シリアル化したりすることができます。
Nest が提供する 8 つのパイプは次のとおりです。
ValidationPipe
ParseArrayPipe
ParseIntPipe
ParseUUIDPipe
ParseBoolPipe
DefaultValuePipe
ParseEnumPipe
ParseFloatPipe
このガイドでは Nest での検証を実証するために、組み込みの ValidationPipe
これにより、リクエスト ペイロードの検証を強制できるようになり、 class-validator
パッケージ;特定のルールは、各モジュールのデータ転送オブジェクト/ローカル クラス宣言内の単純な注釈を使用して宣言されます。
組み込みの使用を開始するには ValidationPipe
から輸出される @nestjs/common
をインストールしましょう。 class-validator
および class-transformer
パッケージ:
$ npm i --save class-validator class-transformer
# Or
$ yarn add class-validator class-transformer
# Or
$ pnpm install class-validator class-transformer
次に、 main.ts
どこで結ばれるのか ValidationPipe
アプリケーションのルート レベルで、アプリケーション内のすべてのエンドポイントが無効なデータを取得しないように保護します。
import { ValidationPipe } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalPipes(new ValidationPipe());
await app.listen(3000);
}
bootstrap();
次に、各モジュールのデータ転送オブジェクト宣言で、個々のデータごとに適切なデータ チェックを宣言することにより、いくつかの検証ルールを追加します。私たちの場合、適切な検証ルールを宣言します。 name
および email
in UpdateUserDto
:
import { IsEmail, IsString } from 'class-validator';
export class UpdateUserDto {
@IsString()
name: string;
@IsEmail()
email: string;
}
@IsString()
デコレータは、指定されたデータが実際の文字列であるかどうかをチェックし、 @IsEmail()
validator は、指定されたデータが電子メールであるかどうかをチェックし、そうでない場合は false を返し、例外をスローします。
さて、作ろうとすると、 PATCH
ユーザー プロファイルにリクエストを送信し、有効な電子メールの代わりに番号を入力すると、例外がスローされます。
これらにより、Nest アプリで非常に優れた検証が行われます。
で検証しながら ValidationPipe
、メソッド ハンドラーに受け取らせたくないプロパティをフィルターすることもできます。たとえば、ハンドラーが期待するだけの場合、 name
および email
プロパティだけでなく、リクエストには country
プロパティを削除できます country
設定による結果のオブジェクトからのプロパティ whitelist
〜へ true
インスタンス化するとき ValidationPipe
:
import { ValidationPipe } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalPipes(
new ValidationPipe({
whitelist: true,
}),
);
await app.listen(3000);
}
bootstrap();
メソッドパラメータレベルでのパイプのバインド
パイプは上でも定義できます params
、 同じように。このために、メソッドのパラメータ レベルでパイプをバインドします。
これまでは、 userId
数値にする場合、次のリクエストを行うとわかります。 userId
文字列として指定しても、次のことに関係なく成功することがわかります。
の値を確実にするには userId
常に数値でなければなりません。バインドすることを宣言します。 getUser()
同じことを保証する検証チェックを備えたメソッド ハンドラー:
...
import { ParseIntPipe } from '@nestjs/common';
@Get('/:userId')
getUser(@Param('userId', ParseIntPipe) userId: number) {
return this.userService.getUser(userId);
}
getUser(userId: number) {
return { userId };
}
ParseIntPipe
組み込みの ParseInt パイプを定義し、実行対象のデータが整数であることを保証します。
さて、 GET
無効な人への要求 userId
文字列「ab」の場合、検証は失敗し、例外がスローされます。 400
ステータスコード:
ただし、数値を指定すると、検証は正常に合格します。
適切な検証を確保するために、他のメソッド ハンドラーを適宜更新することもできます。
import {
Body,
Controller,
Delete,
Get,
Param,
ParseIntPipe,
Patch,
Post,
Req,
} from '@nestjs/common';
import { Request } from 'express';
import { UserService } from './user.service';
@Controller('user')
export class UserController {
constructor(private userService: UserService) {}
@Get()
getUsers() {
return this.userService.get();
}
@Get('/:userId')
getUser(@Param('userId', ParseIntPipe) userId: number) {
return this.userService.getUser(userId);
}
@Post()
store(@Req() req: Request) {
return this.userService.create(req);
}
@Patch('/:userId')
update(
@Body() updateUserDto: { name: string; email: string },
@Param('userId', ParseIntPipe) userId: number,
) {
return this.userService.update(updateUserDto, userId);
}
@Delete()
delete(@Param('userId', ParseIntPipe) userId: number) {
return this.userService.delete(userId);
}
}
import { Injectable } from '@nestjs/common';
import { Request } from 'express';
import { UpdateUserDto } from './dto/user-update.dto';
@Injectable()
export class UserService {
get() {
return { name: 'Uchechukwu Azubuko', country: 'Nigeria' };
}
getUser(userId: number) {
return { userId };
}
create(req: Request) {
return req.body;
}
update(updateUserDto: UpdateUserDto, userId: number) {
return { body: updateUserDto, userId };
}
delete(userId: number) {
return { userId };
}
}
これで、おそらく外部ソースからアプリケーションに取り込まれるデータを、いつでも検証するためのベスト プラクティス手法が確保されました。
まとめ
このガイドでは、Node.js ブロックの最新の機能について学ぶことができました。 Nest.js と、それを使用してアプリケーションを構築したい場合に開始するために必要なものがすべて含まれています。 Nest とは何か、その機能、Nest プロジェクトの作成方法、Nest アプリへの受信データの処理方法、受信データの検証方法を学習しました。全体として、Nest アプリケーションの構成要素と、各コンポーネントが Nest.js アプリケーションにもたらす価値について学習しました。
この時点から、Nest を使用したエンタープライズ グレードのアプリケーションの構築に関して学ぶべきことはまだたくさんありますが、今後のすべての作業を開始して実行できる基本的な概念をうまくカバーすることができました。
今後、Nest と MySQL を使用して RESTful API を構築する方法を学ぶ新しいガイドに注目してください。
読んでくれてありがとう!