TL;DR
- Next.js 15とNode.js 23の組み合わせで、静的ビルド時に謎の型エラーに遭遇。
- 原因はNode.jsの非LTSバージョンによる内部互換性の問題だった。
- 環境を疑う視点と、安定運用のための基本設定の大切さを再確認した。
開発環境の選択が思わぬ落とし穴に
プロジェクトの初期化には create-next-app を使い、TypeScriptとTailwindを組み込んだ。特別なことはしていない。使ったNode.jsのバージョンは、自分の環境で最新として入っていたv23.2.0。安定して動くだろうと思っていた。
ローカルでの next dev は問題なく動いていた。しかし、npm run build を叩いた瞬間、見慣れないエラーが現れた。
npm run build
> frontend@0.1.0 build
> next build
▲ Next.js 15.3.1
Creating an optimized production build ...
Failed to compile.
./app/page.tsx + 1 modules
Unexpected end of JSON input
> Build failed because of webpack errors
エラーから意味が取れず、しばらく固まってしまった。最初はコードのどこかにミスがあるのだろうと思い、型を直したりファイル構成を見直したりしたが、状況は変わらなかった。
調べるうちに、どうやらこの問題は自分のコードだけでなく、Next.jsの内部処理とNode.jsの相性に起因していることがわかってきた。つまり、開発環境のバージョンに問題があったのだ。
「動く」ことと「ビルドできる」ことは別物だった
Node.js v23系はまだLTSではなく、Next.jsが正式にサポートしているのはv18やv20といったLTS版である。自分は知らずに最新版を入れてしまっていたのだ。v23は一部のモジュールの扱いが異なっており、それがNext.jsのApp Routerと静的ビルド処理に食い違いを生じさせていた。
例えば params に渡されるオブジェクトの型が、ビルド時に「Promiseとして解釈される」挙動になってしまい、TypeScript上では問題ないように見えても、Next.jsのビルドフェーズで弾かれてしまう。ローカルでは動いていたため気づきにくく、ハマりどころとしてはかなり深い。
Node.jsのバージョンをv20に切り替え、.nvmrcを置いてnvmで管理するようにしたところ、ようやくビルドが通った。原因さえわかってしまえば解決は簡単なのだが、そこに至るまでに感じたもどかしさと違和感は、なかなか消えなかった。
自分の環境を信じすぎない
今回のことから学んだのは、「ローカルで動く=正しい」ではないという当たり前の事実だった。特にNext.jsのようにビルド工程が複雑なフレームワークでは、Node.jsの微妙なバージョン違いが予期せぬバグを引き起こす。
開発を始める前に、公式ドキュメントに記載されている「推奨環境」に目を通すのはやはり大事で、それは単なる保守的な態度ではなく、リスクを避ける知恵だと感じた。技術的に「できる」ことと、「安定して動く」ことのあいだには、しばしば大きな差がある。
また、.nvmrcのような仕組みを通じて、環境をチームや未来の自分と共有できる形にしておくことも、開発の安心感を大きく高めてくれる。知らずに新しいバージョンを使ってしまう、という事故を防ぐためにも有効だ。
なぜこの小さな経験を書き残したくなったのか
技術的な知識としては些細なことかもしれない。Node.jsのバージョンを揃える、という話だけなら数行で済む。でも、自分にとっては「開発と向き合う態度」について、あらためて考えるきっかけになった。
新しい技術を積極的に取り入れるのは楽しいし、意味のあることだと思っている。でも同時に、自分の使っている道具の足元を確かめることも、同じくらい大切だ。そういう静かな態度が、結局はものづくりの質を支えていくのではないか。雨の日の鎌倉で、そんなことを感じながらコードを書いていた。
⸻
参考:
• https://nextjs.org/docs/app/building-your-application/deploying/nodejs-version
• https://nodejs.org/en/about/releases