🐙
学習ログ|Prisma × Next.js × Docker ビルドで出たエラーと学び
はじめに
Docker で Next.js + Prisma アプリをビルドするときに、いくつかハマりどころがあった。ここでは実際に遭遇したエラーと、それを直す過程で学んだことを記録する。
前提知識
Prisma
- Node.js で使える ORM(Object Relational Mapping)。
- Prisma Client を自動生成して DB に型安全にアクセスできる。
-
@prisma/client
を dependencies に入れ、npx prisma generate
を実行すると、node_modules/@prisma/client
以下にクライアントコードが生成される。
next.config.ts
- Next.js のプロジェクト全体の設定ファイル。
- ここに実験的機能や外部パッケージの扱いを定義できる。
- バージョンによってキーの名前が変わることがある(今回のケースでは
serverComponentsExternalPackages
→serverExternalPackages
)。
App Router
- Next.js 13 以降で導入された新しいルーティングシステム。
- API ルートは
src/app/api/.../route.ts
に定義し、GET
/POST
/DELETE
などの関数をエクスポートする。 - 関数の引数型は Next.js 側に決まっていて、誤るとビルドエラーになる。
ESLint
- JavaScript/TypeScript の静的解析ツール。
- コードスタイルや型の安全性を保つためにルールを設定できる。
- 今回は「
any
を禁止する」というルールに引っかかってビルドが失敗した。
学んだエラーと対応
1. Prisma Client が見つからない
Error: Cannot find module ‘/app/node_modules/@prisma/client/generator’
-
原因
-
@prisma/client
がdevDependencies
に入っていて本番では消えていた -
npx prisma generate
を schema コピー前に実行していた
-
-
対応
-
@prisma/client
を dependencies に移動 - Dockerfile で schema をコピーした後に
npx prisma generate
を一度だけ実行 - または postinstall に任せて、Dockerfile 側では実行しない
-
2. next.config.ts の設定警告
Unrecognized key(s) in object: ‘serverComponentsExternalPackages’
-
原因
Next.js 15 からキー名が変更された -
対応
// before experimental: { serverComponentsExternalPackages: ['@prisma/client'], } // after serverExternalPackages: ['@prisma/client'],
3. ESLint による any 禁止
Unexpected any. Specify a different type.
- 原因: ESLint が any を禁止していた
- 対応: unknown を使い、最低限の型チェックを追加
type CastInput = { name: string }
export async function POST(req: Request) {
const data: unknown = await req.json()
if (typeof data !== 'object' || data === null || typeof (data as any).name !== 'string') {
return new Response(JSON.stringify({ error: 'Invalid payload' }), { status: 400 })
}
const input = data as CastInput
return new Response(JSON.stringify({ ok: true }))
}
- 一時的に無効化したい場合は、その行にだけ ESLint コメントを付ける
// eslint-disable-next-line @typescript-eslint/no-explicit-any
4. App Router の型エラー
Route "src/app/api/casts/[id]/route.ts" has an invalid "DELETE" export
- 原因: 第二引数の型を { params: { id: string } } と固定していたが、Next.js は Record<string, string | string[]> を期待している
- 対応
export async function DELETE(
req: Request,
{ params }: { params: Record<string, string | string[]> }
) {
const raw = params.id
const id = Array.isArray(raw) ? raw[0] : raw
if (!id) {
return new Response(JSON.stringify({ error: 'Missing id' }), { status: 400 })
}
return new Response(JSON.stringify({ ok: true }))
}
まとめ
- Prisma → @prisma/client は dependencies に入れる & 生成タイミングを整理
- next.config.ts → バージョンアップでキー名が変わることがある
- ESLint → any 禁止ルールに従い、unknown + 型ガードで安全に処理
- App Router → 引数型は Next.js が定める形(Record<string, string | string[]>)に合わせる
タグ
#Nextjs #Prisma #Docker #TypeScript #学習ログ
Discussion