📝
NestJSでmonorepoがいい感じ
何らかのアプリケーションと、その管理アプリケーションを開発するみたいなよくあるケース、
NestJSでサポートされているmonorepo機能を使うといい感じだったので備忘録も兼ねて
やってみる
1. NestJSプロジェクトの作成
まずは通常通りnest new
でNestJSプロジェクトを新規作成します
bash
npx nest new my-app
するとディレクトリ構成はこんな感じになります
.
├── README.md
├── nest-cli.json
├── package-lock.json
├── package.json
├── src
│ ├── app.controller.spec.ts
│ ├── app.controller.ts
│ ├── app.module.ts
│ ├── app.service.ts
│ └── main.ts
├── test
│ ├── app.e2e-spec.ts
│ └── jest-e2e.json
├── tsconfig.build.json
└── tsconfig.json
2. 管理アプリケーションを追加する
では先ほど作ったmy-app
の管理アプリケーションとしてadmin-app
作っていきます
bash
npx nest g app admin-app
するとディレクトリ構成が変更されて以下のようにapps/
配下にmy-app
とadmin-app
が配置されます
.
├── README.md
├── apps
│ ├── admin-app
│ │ ├── src
│ │ │ ├── admin-app.controller.spec.ts
│ │ │ ├── admin-app.controller.ts
│ │ │ ├── admin-app.module.ts
│ │ │ ├── admin-app.service.ts
│ │ │ └── main.ts
│ │ ├── test
│ │ │ ├── app.e2e-spec.ts
│ │ │ └── jest-e2e.json
│ │ └── tsconfig.app.json
│ └── my-app
│ ├── src
│ │ ├── app.controller.spec.ts
│ │ ├── app.controller.ts
│ │ ├── app.module.ts
│ │ ├── app.service.ts
│ │ └── main.ts
│ ├── test
│ │ ├── app.e2e-spec.ts
│ │ └── jest-e2e.json
│ └── tsconfig.app.json
├── nest-cli.json
├── package-lock.json
├── package.json
├── tsconfig.build.json
└── tsconfig.json
3. それぞれ起動してみる
nest-cli
でそれぞれのアプリを起動します
nest-cli
の設定はnest-cli.json
にあり、先ほど実行したコマンドに応じて自動で更新してくれています
projects
にあるのがそれぞれのアプリの設定ですね
nest-cli.json
{
"$schema": "https://json.schemastore.org/nest-cli",
"collection": "@nestjs/schematics",
"sourceRoot": "apps/my-app/src",
"monorepo": true,
"root": "apps/my-app",
"compilerOptions": {
"webpack": true,
"tsConfigPath": "apps/my-app/tsconfig.app.json"
},
"projects": {
"my-app": {
"type": "application",
"root": "apps/my-app",
"entryFile": "main",
"sourceRoot": "apps/my-app/src",
"compilerOptions": {
"tsConfigPath": "apps/my-app/tsconfig.app.json"
}
},
"admin-app": {
"type": "application",
"root": "apps/admin-app",
"entryFile": "main",
"sourceRoot": "apps/admin-app/src",
"compilerOptions": {
"tsConfigPath": "apps/admin-app/tsconfig.app.json"
}
}
}
}
起動にあたり、my-app
とadmin-app
が同じPORTで起動する設定になっている箇所だけ変更しておきます
apps/admin-app/src/main.ts
import { NestFactory } from '@nestjs/core';
import { AdminAppModule } from './admin-app.module';
async function bootstrap() {
const app = await NestFactory.create(AdminAppModule);
await app.listen(3001); // 3000から3001に
}
bootstrap();
以下コマンドで起動
bash
npx nest start my-app
npx nest start admin-app
4. 共通レイヤーも作成してみる
NestJSでは各アプリから利用する共通コードをlibrary
として管理することができます
my-core
というlibraryを作ってみます
npx nest g library my-core
作成するとディレクトリ構成は以下のようになります
.
├── README.md
├── apps
│ ├── admin-app
│ │ ├── src
│ │ │ ├── admin-app.controller.spec.ts
│ │ │ ├── admin-app.controller.ts
│ │ │ ├── admin-app.module.ts
│ │ │ ├── admin-app.service.ts
│ │ │ └── main.ts
│ │ ├── test
│ │ │ ├── app.e2e-spec.ts
│ │ │ └── jest-e2e.json
│ │ └── tsconfig.app.json
│ └── my-app
│ ├── src
│ │ ├── app.controller.spec.ts
│ │ ├── app.controller.ts
│ │ ├── app.module.ts
│ │ ├── app.service.ts
│ │ └── main.ts
│ ├── test
│ │ ├── app.e2e-spec.ts
│ │ └── jest-e2e.json
│ └── tsconfig.app.json
├── dist
│ └── apps
│ ├── admin-app
│ │ └── main.js
│ └── my-app
│ └── main.js
├── libs
│ └── my-core
│ ├── src
│ │ ├── index.ts
│ │ ├── my-core.module.ts
│ │ ├── my-core.service.spec.ts
│ │ └── my-core.service.ts
│ └── tsconfig.lib.json
├── nest-cli.json
├── package-lock.json
├── package.json
├── tsconfig.build.json
└── tsconfig.json
nest-cli.json
のprojectsにも、"type":"library"
として追加されています
nest-cli.json
{
"$schema": "https://json.schemastore.org/nest-cli",
"collection": "@nestjs/schematics",
"sourceRoot": "apps/my-app/src",
"monorepo": true,
"root": "apps/my-app",
"compilerOptions": {
"webpack": true,
"tsConfigPath": "apps/my-app/tsconfig.app.json"
},
"projects": {
"my-app": {
"type": "application",
"root": "apps/my-app",
"entryFile": "main",
"sourceRoot": "apps/my-app/src",
"compilerOptions": {
"tsConfigPath": "apps/my-app/tsconfig.app.json"
}
},
"admin-app": {
"type": "application",
"root": "apps/admin-app",
"entryFile": "main",
"sourceRoot": "apps/admin-app/src",
"compilerOptions": {
"tsConfigPath": "apps/admin-app/tsconfig.app.json"
}
},
+ "my-core": {
+ "type": "library",
+ "root": "libs/my-core",
+ "entryFile": "index",
+ "sourceRoot": "libs/my-core/src",
+ "compilerOptions": {
+ "tsConfigPath": "libs/my-core/tsconfig.lib.json"
+ }
+ }
}
}
作成したmy-core
をアプリから利用する場合はこんな感じです
libs/my-core/src/index.ts
export * from './my-core.module';
export * from './my-core.service';
+ export const hello = 'hello monorepo';
apps/my-app/src/app.service.ts
+ import { hello } from '@my-core/my-core';
import { Injectable } from '@nestjs/common';
@Injectable()
export class AppService {
getHello(): string {
+ return hello;
- return "Hello World!"
}
}
library作成時に自動でimportプレフィックスも作成してくれているのもいいですね👍
そしてもちろんそれぞれ別個にbuildが可能です
npx nest build my-app
npx nest build admin-app
npx nest build my-core
dist
├── apps
│ ├── admin-app
│ └── my-app
└── libs
└── my-core
参考
Discussion