💨

Nest.js で start:prod 実行時に Error: Cannot find module 'dist/main' と表示される

2024/02/05に公開

背景

Cykinso の 研究&データ技術開発 の山﨑です。

Nest.js で本番環境のために npm run build し、正常に build できているか試すために npm run start:prod を実行したところ、以下のエラーが出てしまいました。

> npm run start:prod

> backend@0.0.1 start:prod
> node dist/main

node:internal/modules/cjs/loader:1147
  throw err;
  ^

Error: Cannot find module '/workspace/xxxxx/dist/main'
    at Module._resolveFilename (node:internal/modules/cjs/loader:1144:15)
    at Module._load (node:internal/modules/cjs/loader:985:27)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:135:12)
    at node:internal/main/run_main_module:28:49 {
  code: 'MODULE_NOT_FOUND',
  requireStack: []
}

Node.js v20.10.0

エラーでググってもあまり同じ例が出てこなかったので今後困った方のためにメモしておきます。

原因

ORM で Prisma を利用していましたが prisma ディレクトリが以下のようにルートディレクトリ下に存在していることが原因でした。
(この構成自体は Prisma を利用する時のものとして正しいです)

> tree . -L 1
.
├── dist
├── nest-cli.json
├── node_modules
├── package.json
├── package-lock.json
├── prisma
├── README.md
├── src
├── test
├── tsconfig.build.json
└── tsconfig.json

この状態で npm run build すると以下の dist ディレクトリ下に prisma, src ディレクトリが作成され、本来 dist ディレクトリ直下に置かれるべき main.tssrc ディレクトリの中に存在するようになってしまいます。

> tree dist -L 2
dist
├── prisma
│   ├── seed.d.ts
│   ├── seed.js
│   └── seed.js.map
├── src
│   ├── app.controller.d.ts
│   ├── app.controller.js
│   ├── app.controller.js.map
│   ├── app.module.d.ts
│   ├── app.module.js
│   ├── app.module.js.map
│   ├── app.service.d.ts
│   ├── app.service.js
│   ├── app.service.js.map
│   ├── main.d.ts
│   ├── main.js
│   ├── main.js.map
│   ├── prisma
│
│   ...skipping
│
└── tsconfig.build.tsbuildinfo

解決方法

tsconfig.build.jsonbuild 対象外にする設定 exclude がありますのでそちらに prisma ディレクトリを追加します。

tsconfig.build.json
{
  "extends": "./tsconfig.json",
  "exclude": ["node_modules", "test", "dist", "**/*spec.ts", "prisma"]
}

再度 npm run build を実行するとディレクトリ構成が変わり、期待通り main.jsdist ディレクトリ直下に存在しています。

> npm run build

> backend@0.0.1 build
> nest build

> $ tree dist -L 1
dist
├── app.controller.d.ts
├── app.controller.js
├── app.controller.js.map
├── app.module.d.ts
├── app.module.js
├── app.module.js.map
├── app.service.d.ts
├── app.service.js
├── app.service.js.map
├── main.d.ts
├── main.js
├── main.js.map
├── prisma
...skipping

無事に npm run start:prod も実行することができました。

> npm run start:prod

> xxxxx@0.0.1 start:prod
> node dist/main

[2:23:31 AM] File change detected. Starting incremental compilation...

[2:23:31 AM] Found 0 errors. Watching for file changes.

[Nest] 37427  - 01/18/2024, 2:23:43 AM     LOG [NestFactory] Starting Nest application...
[Nest] 37427  - 01/18/2024, 2:23:43 AM     LOG [InstanceLoader] DynamooseModule dependencies initialized +17ms
[Nest] 37427  - 01/18/2024, 2:23:43 AM     LOG [InstanceLoader] ConfigHostModule dependencies initialized +0ms
[Nest] 37427  - 01/18/2024, 2:23:43 AM     LOG [InstanceLoader] AppModule dependencies initialized +0ms
[Nest] 37427  - 01/18/2024, 2:23:43 AM     LOG [InstanceLoader] ConfigModule dependencies initialized +0ms
...skipping

💡 まとめ

ディレクトリ下にあった prisma ディレクトリ (TypeScript file全般で起こることだと思います) が npm run build 時に含まれてしまうことが原因でした。
tsconfig.build.json で build 時に含まれないように設定しましょう。

Cykinso's Tech Blog

Discussion