今日からはじめるNest.js入門
1.Nest.jsとは
フレームワークを理解するには、その思想や概念を把握することが非常に重要です。
そのため、公式サイトのイントロダクションやフィロソフィーを参照してみましょう。
とあります。
Nest.jsは次のような特徴を持っているとされています。
この記事ではNest.jsの概念を理解するために焦点を当てています。
Nest.jsはサーバーサイドフレームワークであり、AWSのElastic BeanstalkやEC2、GCPのAppEngineやCloud Runなどのようなサーバーサイドで動作するRailsやLaravelと同様のフレームワークです。
Nest.jsはモノリシックなアプリケーションを作成することもできますし、フロントエンドとバックエンドが分離したアーキテクチャでバックエンドを担当することも可能です。
従来、Node.jsではExpressが主流でしたが、Expressはミドルウェア的な位置づけであり、完全なサーバーサイドフレームワークとは言いにくい側面がありました。
Nest.jsの登場により、Node.jsの世界でも堅牢なサーバーサイドフレームワークが提供されるようになりました。
2.Nest.jsのストラクチャー構造
では、もう少し具体的にNest.jsの機能を見ていきましょう。
// CLIをインストールする
$ npm i -g @nestjs/cli
// Nest.jsプロジェクトを作成する
$ nest new nest-sample
// サーバーを起動する
$ cd nest-sample
$ npm run start:dev
プロジェクトを作成し、サーバーを起動するとlocalhost:3000で"Hello World"が表示されます。
では、プロジェクトのストラクチャーを見てみましょう。
src
├── main.ts
├── app.controller.spec.ts
├── app.controller.ts
├── app.module.ts
├── app.service.ts
srcディレクトリ以下にはmain.tsとapp module関連のファイルが配置されています。
├── main.ts // nest.jsのエントリーポイント、サーバのインスタンスを作成しlistenしている
├── app.controller.spec.ts // controllerのテストファイル
├── app.controller.ts // ルーティングと、どの処理へと繋ぐかを判断するcontrollerファイル
├── app.module.ts // controllerとserviceをまとめるmoduleファイル
├── app.service.ts // MVC的に言うとMの部分で処理のメインロジックを担当するファイル
Nest.jsでは、controllerとserviceをモジュールに読み込んで使用しています。それぞれの中身を見ていきましょう。
// main.ts
async function bootstrap() {
// create()の引数にはルートモジュールを指定
const app = await NestFactory.create(AppModule);
// 3000番ポートでサーバを起動する
await app.listen(3000);
}
bootstrap();
// app.controller.ts
// controller作成初期はここまで存在しませんが代表的な書き方を列挙しておきます。
import { Controller, Get, Req } from '@nestjs/common';
import { Request } from 'express';
// Controllerデコレーター
// @Controller('hello')のように引数でもパス指定が可能
@Controller()
export class AppController {
// constructorに入れることで自動でDIする
constructor(private readonly appService: AppService) {}
// Getメソッドの場合はここで受け取る
// @Get('hello')のように引数でもパス指定が可能。
@Get()
findAll(): string {
// 実際の処理はservice側で行う
return this.appService.findAll();
}
// :idとすることで/123や/3826などパラメーターを動的に受け取る
@Get(':id')
findOne(@Param() params): string {
console.log(params.id);
return `paramsのidは${params.id}です。`;
}
// /search?id=4や/search?id=4&word=今日の天気、のようなクエリーを受け取る
@Get('search')
findQuery(@Query() query: { id: string, word: string }) {
return `idは${query.id}で、wordは${query.word}です。`;
}
// BodyやHeaderなど様々なリクエストデータを受け取る
@Get()
findRequest(@Req() request: Request): string {
console.log(request);
return 'リクエストを受け取りました';
}
// Postメソッドの場合ここでリクエストBodyを受け取る
// create(@Body: createDto: CreateCatDto): string のように、
// dtoを引数で指定できそのままreturn this.appService.create(createDto);とすることができる
@Post()
create(@Body: id: number, @Body name: string, @Body email: string): string {
return this.appService.create(id, name, email);
}
// idを受け取って更新する
@Put(':id')
update(@Param('id') id: string, @Body() updateCatDto: UpdateCatDto) {
return this.appService.update(id);
}
// idを受け取って削除する
@Delete(':id')
remove(@Param('id') id: string) {
return this.appService.delete(id);
}
}
// app.service.ts
// @injectableとすることでproviderとして認識されてDIできるようになる
@Injectable()
export class AppService {
// 各ロジックを記述していく
findAll(): string {
return 'Hello World!';
}
findOne(id: string): string {
return '...';
}
}
// app.module.ts
// このアプリのルートモジュール
@Module({
// importsの配列の中に他のmoduleを入れると別のmoduleをimportすることが可能になる
imports: [], // [userModule, AuthorModule, productModule]
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
アプリを作る際には、ルートごとにディレクトリが切られます。
具体的には、/usersや/itemsなどのルートに対応するディレクトリが作成されます。
以下のファイルを1つの基本セットとして作成していきましょう。
それでは、以下のように/usersと/userのファイル郡を作成してみましょう。
├── main.ts
├── app.controller.spec.ts
├── app.controller.ts
├── app.module.ts
├── app.service.ts
├── users // usersルーティングの処理
├── dto
│ ├── create-user.dto.ts
│ └── update-user.dto.ts
├── entities
│ └── user.entity.ts
├── users.controller.spec.ts
├── users.controller.ts
├── users.module.ts
├── users.service.spec.ts
└── users.service.ts
dtoとentitiesは、Nest.jsにおけるディレクトリの一部です。
以下でそれぞれの役割を説明します。
Nest.jsでは、認証処理やエラー処理、リクエストやレスポンスに対して行いたい共通の処理であるミドルウェアを簡単に導入することができます。
ミドルウェアは、アプリケーション全体や特定のエンドポイントに対して、リクエストが処理される前後で追加の処理を実行するために使用されます。例えば、リクエストの認証や承認、データの検証、エラーハンドリングなどの処理をミドルウェアで行うことができます。
3.Nest.jsの概念図
ストラクチャーを深堀りして見えてきた構成図は以下のようになります。
Nest.jsでは、前述のような構成でアプリケーションが動作しています。
今回はミドルウェアについては省略しましたが、サーバーサイドで認証や認可が必要な場合は欠かせない要素ですので、一緒に学んでいきたいと思います。
ミドルウェアを使用することで、リクエストやレスポンスに対して追加の処理や検証を行うことができます。
例えば、認証ミドルウェアを組み込むことで、リクエストを受ける前にユーザーの認証状態を確認し、必要な権限を持っているかをチェックすることができます。
Nest.jsのミドルウェアについても一緒に学んでいくことで、よりセキュアで柔軟なサーバーアプリケーションを構築することができるでしょう。
それでは。