Nest.js とは
Nest.jsとはNode.jsのサーバーサイドフレームワークです。TypeScript(以下TS)での開発がメインとなりますが、JavaScript(以下JS)での開発も可能です。
Express(デフォルト)もしくはFastify(オプション)といったHTTPサーバーフレームワークをコアに動作する仕組みとなっており、実際これらのHTTPサーバーフレームワークからメソッド等をimport
してきて使うことも可能です。
アーキテクチャはAngularに強い影響を受けており、デコレーターを活用したコードの記述や開発ルールの強制の仕方/実装と疎結合になるディレクトリ構成にはその影響が伺えます。ただこうした硬めな印象を受けるアーキテクチャのアプローチは、これまで決定打がなく問題となっていたNode.js/サーバーサイドJS開発のアーキテクチャの難しさを解決するものとなっております。
こうしたTSフレンドリーかつアーキテクチャ設計が受け入れられたのか、国内でもここ1~2年の間に採用事例が増えており、今後も増えることが予想されます。
また、その他の特徴としては以下が挙げられます。
- RESTAPIだけではなく、もちろんGraphQLサーバーの開発も可能
- Nest CLIで簡単にアプリやファイルのテンプレートを作成出来る
- テスト用フレームワークがすでに用意されており、疎結合な構成のおかげでテストコードの作成が容易
- OpenAPI(Swagger)のサポート(要プラグイン)
- 豊富な公式ドキュメントとサンプル集
ちなみに公式サイトのハンバーガーメニューが本当にハンバーガーになっている遊び心は個人的にすごく好きです。
では、今回は初期生成されるNest.jsアプリを見ながら、まず基本構造を見ていきたいと思います(本当はサンプルも作るつもりだったのですが、余裕で間に合わなかったのでこれはまた別の機会に…)。
開発環境
MacBook Pro(M1 2020)
macOS Monterey 12.1
Nest CLIのインストールとアプリの初期生成
アプリのテンプレートを引っ張ってくるため、まずNest CLIをインストールします。
# npmの場合
# npm i -g @nestjs/cli
yarn global add @nestjs/cli
which nest
# /Users/hogehoge/.yarn/bin/nest と返却されたのでNest CLIがインストールされたことが確認できた
# nest new <プロジェクト名> で生成可能
nest new nest new nestjs-simple-tutorial
⚡ We will scaffold your app in a few seconds..
CREATE nestjs-simple-tutorial/.eslintrc.js (631 bytes)
CREATE nestjs-simple-tutorial/.prettierrc (51 bytes)
CREATE nestjs-simple-tutorial/README.md (3339 bytes)
CREATE nestjs-simple-tutorial/nest-cli.json (64 bytes)
CREATE nestjs-simple-tutorial/package.json (2011 bytes)
CREATE nestjs-simple-tutorial/tsconfig.build.json (97 bytes)
CREATE nestjs-simple-tutorial/tsconfig.json (546 bytes)
CREATE nestjs-simple-tutorial/src/app.controller.spec.ts (617 bytes)
CREATE nestjs-simple-tutorial/src/app.controller.ts (274 bytes)
CREATE nestjs-simple-tutorial/src/app.module.ts (249 bytes)
CREATE nestjs-simple-tutorial/src/app.service.ts (142 bytes)
CREATE nestjs-simple-tutorial/src/main.ts (208 bytes)
CREATE nestjs-simple-tutorial/test/app.e2e-spec.ts (630 bytes)
CREATE nestjs-simple-tutorial/test/jest-e2e.json (183 bytes)
# どのパッケージ管理ツールを使うかの質問が来る。今回はyarnを選択。
Which package manager would you ❤️ to use?
npm
❯ yarn
pnpm
🚀 Successfully created project nestjs-simple-tutorial
👉 Get started with the following commands:
$ cd nestjs-simple-tutorial
$ yarn run start
Thanks for installing Nest 🙏
Please consider donating to our open collective
to help us maintain this package.
🍷 Donate: https://opencollective.com/nest
# 生成されたnestjs-simple-tutorialディレクトリをvscodeで開く
$ cd nestjs-simple-tutorial && code .
初期生成されたアプリについて
サーバーの立ち上げ
yarn run start
# 叩くと `dist/`フォルダが生成される
yarn run v1.22.17
$ nest start
[Nest] 23190 - 2022/03/01 8:38:00 LOG [NestFactory] Starting Nest application...
[Nest] 23190 - 2022/03/01 8:38:00 LOG [InstanceLoader] AppModule dependencies initialized +30ms
[Nest] 23190 - 2022/03/01 8:38:00 LOG [RoutesResolver] AppController {/}: +2ms
[Nest] 23190 - 2022/03/01 8:38:00 LOG [RouterExplorer] Mapped {/, GET} route +1ms
[Nest] 23190 - 2022/03/01 8:38:00 LOG [NestApplication] Nest application successfully started +1ms
http://localhost:3000/ へアクセスすると、Hello World! の文字が!
ちなみにyarn run start
をyarn run start:dev
に変更することで、ファイルを編集&保存する度にサーバーがリロードされて変更内容を反映してくれるので、今後はこちらを使っていこうと思います。
ディレクトリ階層について
メインはsrc
フォルダとなります。
root直下にはE2Eテスト用のtestフォルダもいるが、今回は触れません。
src/
|- app.controller.spec.ts
|- app.controller.ts
|- app.module.ts
|- app.service.ts
|- main.ts
では一つずつ説明していきます。
まずNest.jsでサーバーを立ち上げる上で以下の4つのファイルが必須となります。
- main
- controllers
- providers
- modules
これらの役割を先程のsrc/
直下のファイルと紐付けながら説明していきます。
main.ts
mainの役割を司るのがこのファイルです。
Nest.jsアプリのエントリーポイントとなり、サーバのインスタンスを作成&サーバーの起動はこのファイルからのみ行います。
Expressを扱ったことがある人にはconst app = express()
〜app.listen()
と同じことしているなぁって思ってもらえば大丈夫です。
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
// NestFactoryというFunctionでNest.jsアプリのインスタンスを生成
const app = await NestFactory.create(AppModule);
// 3000番portでサーバーを立ち上げる
await app.listen(3000);
}
bootstrap();
app.controller.ts / app.controller.spec.ts
controllers
の役割を司るファイルです。サーバーのルーティングを行う箇所です。
初期コードでは@Get()
デコレーターを使用し、GETで[rootURL]/
を叩いたとき呼び出されるgetHello
メソッドが定義されています。
今回は触れませんが、いわゆるリダイレクトや認証確認などのガード処理もここで設定します。
AppService
については後で説明します。
import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';
@Controller()
export class AppController {
constructor(private readonly appService: AppService) {}
@Get()
getHello(): string {
return this.appService.getHello();
}
}
なお、app.controller.spec.ts
は JS/TS のユニットテスト作成ライブラリであるJest を使って、app.controller.ts
のテストコードを作成する箇所です。
app.service.ts
providers
の役割を司るファイルです。controllers
の処理を詳細に定義する場所だと思ってもらえば大丈夫です。
今回は詳しく触れませんが、ここでは@Injectable()
デコレーターを使用しており、DI(Dependency Injection/依存性注入)の仕組みが使用されています。
DIについてもっと知りたい方はこちらの資料を読んでみてください。
import { Injectable } from '@nestjs/common';
@Injectable()
export class AppService {
// APIが呼び出されたときに'Hello World!'を返却するメソッドを定義
getHello(): string {
return 'Hello World!';
}
}
app.module.ts
modules
の役割を司るファイルです。controllers
とかproviders
を取りまとめるところです。
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
@Module({
imports: [],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
以上、Nest.jsの基本構造の解説でした。
今後したいこと
Angularライクな書き方にまだまだ慣れていないので、まずは公式のOverviewの全ページを一周しようと思っています。そこからずっと勉強できてなかったTypeORMの活用やGraphQL実装あたりにも踏み込めればと思っています。
参考にしたページ