個人開発でNext.jsを選んだ理由と、正直な後悔
このサイトはNext.js(App Router)で作っている。個人サイトにNext.jsを選んだのは正解だったのか。良かった点と後悔を正直に書く。
選んだ理由
Reactの知識がそのまま使える。仕事でReactを触ることがあるから、学習コストが低かった。新しいフレームワークを一から覚える余裕はなかったし、「仕事で使う技術の延長線上で個人開発をする」のが自分のスタイルに合っている。
週末に数時間しか取れない個人開発の時間で、フレームワークの基礎から学び直すのは現実的じゃない。Reactのコンポーネント設計やhooksの知識がそのまま活きるNext.jsなら、やりたいことに集中できる。
App Routerを試したかった。Next.js 13以降のApp RouterとReact Server Componentsは、発表された時から気になっていた。ただ、仕事のプロジェクトでいきなり採用するのはリスクがある。個人サイトなら壊れても誰にも怒られない。本番環境で新しい技術を試す場として、ちょうど良かった。
実際、App Routerの layout.tsx によるネストレイアウトの仕組みは、Pages Routerとはまったく考え方が違う。個人サイトで先に触れておいたおかげで、仕事でApp Routerの話が出た時にスムーズに議論できた。
情報量の多さ。Next.jsはユーザー数が多いから、困った時にGoogle検索すれば解決策が見つかる。Stack OverflowにもGitHub Issuesにも先人の知恵がある。マイナーなフレームワークだと「同じエラーに遭遇した人が誰もいない」みたいな状況になりがちで、そこで時間を溶かしたくなかった。
あと、Claude CodeやCopilotといったAIツールとの相性も決め手だった。Next.jsはトレーニングデータに大量のコード例が含まれているから、AIにコード生成させた時の精度が高い。これは地味に大きい。
良かった点
ファイルベースルーティングの手軽さ。app/blog/[slug]/page.tsx を作るだけでルーティングが完成する。設定ファイルを書かなくていい。ブログ記事を追加する時も、ルーティングのことを一切考えなくていいのは快適だった。
ディレクトリ構造がそのままURLになるから、プロジェクトの見通しも良い。app/about/page.tsx は /about、app/blog/page.tsx は /blog。初見でもどのファイルがどのページに対応しているか一目でわかる。
静的生成の手軽さ。generateStaticParams で全ページを事前生成できる。ビルド時にHTMLが生成されるから、ランタイムのパフォーマンスが良い。ブログ記事は更新頻度が低いから、静的生成との相性が抜群だった。
具体的には、Markdownファイルをビルド時にJSONに変換して、そのJSONから静的ページを生成する流れにしている。ランタイムではファイルシステムに一切アクセスしない。この設計はCloudflare Workersにデプロイする上でも都合が良かった(Workersでは fs モジュールが使えないので)。
TypeScriptとの相性。型安全にコンポーネントを書ける。propsの型定義があるから、コンポーネント間のデータの受け渡しでバグが起きにくい。個人開発だとテストを書くのをサボりがちだけど、型チェックがあるだけでかなり安心感がある。
後悔していること
オーバースペック感が否めない。個人サイトに App Router は正直やりすぎだった。Server Components、Streaming、Parallel Routes、Intercepting Routes。Next.jsが提供する機能のうち、自分が使っているのは全体の2割くらいだと思う。
静的なブログサイトなら、AstroやHugoの方がシンプルに作れた。Astroなんてコンテンツ特化のフレームワークだから、Markdownのブログを作るなら最適解に近い。Hugoはビルドが爆速で、100記事だろうが1000記事だろうが1秒かからずにビルドが終わる。
Next.jsは機能が豊富すぎて、個人サイトの規模には合わない。サッカーの試合にF1マシンで乗り込むような感じ。
ビルド時間の増加。ページ数が増えるとビルドが遅くなる。今は23記事で約40秒。まだ許容範囲だけど、100記事になったら2〜3分かかりそうな予感がある。Hugoなら100記事でも0.5秒で終わる世界なので、ここは明確に負けている。
next build の出力を見ていると、静的ページの生成よりもWebpackのバンドル処理に時間がかかっている印象がある。依存パッケージを増やすたびにビルド時間が伸びるので、パッケージの追加には慎重になった。
Cloudflare Workers互換の苦労。Next.jsはVercelに最適化されている。Cloudflare Workersにデプロイするには @opennextjs/cloudflare を使う必要があり、互換性の問題に何度もハマった。
next/og の ImageResponse が動かない、Node.js固有のAPIが使えない、バンドルサイズの上限に引っかかる。一つ一つは解決可能だけど、積み重なると「Vercelにデプロイしていればこの苦労は全部なかったのに」と思う瞬間がある。フレームワークとデプロイ先の相性は、最初にちゃんと検討すべきだった。
依存関係のアップデートが面倒。Next.jsは開発サイクルが速くて、メジャーバージョンアップが年に1〜2回ある。App Routerはまだ成熟途上で、マイナーバージョンでも挙動が変わることがある。next をアップデートしたらビルドが通らなくなって、2時間くらい原因調査に費やしたことが一度あった。
「シンプルに作ればよかった」
一番の後悔は、最初からシンプルに作らなかったこと。
アニメーション、ダークテーマ、スクロールエフェクト、ページ遷移のトランジション。見た目にこだわった結果、コード量が増えた。Framer Motionを入れたり、CSS変数でテーマ切り替えを実装したり。楽しかったけど、冷静に考えると個人サイトに必要だったのは、読みやすいテキストと速い表示速度だけだった。
見た目の凝ったサイトを作った直後は満足感があるけど、1ヶ月後にコードを見返すと「なんでこんな複雑にしたんだろう」と思う。個人開発あるある。
それでもNext.jsで良かった理由
後悔はいくつかあるけど、トータルではNext.jsで良かったと思っている。
学びの量が段違い。App Router、React Server Components、Cloudflare Workers互換、OGP画像生成、Markdown処理パイプライン。この個人サイトを作る過程で触れた技術の幅は、AstroやHugoで作っていたら得られなかったもの。
AIとの相性が良い。Claude CodeでUIコンポーネントを生成させる時、Next.jsのコードはかなりの精度で出してくれる。「App Routerのlayout.tsxで共通ヘッダーを実装して」「generateMetadataでOGP設定して」みたいな指示で、ほぼそのまま使えるコードが出てくる。マイナーなフレームワークだとこうはいかない。
拡張性に余裕がある。ブログ機能の追加、OGP画像の自動生成、API Routes。やりたいことが増えた時に、Next.jsなら大抵のことは対応できる。今は使っていないけど、将来的にRSSフィードやサイトマップの自動生成を追加する時も、Next.jsのAPIを使えば簡単にできる。
個人開発のフレームワーク選びに正解はない。目的と状況に合ったものを選ぶしかない。自分の場合は「学びの最大化」が目的だったから、Next.jsは正解だった。コスパを重視するなら別の選択肢がある。それだけの話。
関連記事
他の記事
ブラウザ横スクロールアクションゲーム開発記|TypeScript×Canvasで作るネオンランナー
HTML5 CanvasとTypeScriptで横スクロールアクションゲーム「ネオンランナー」を自作した。物理エンジン、衝突判定、操作性の工夫を解説する。
ブラウザで遊べるテトリス風パズルをTypeScriptで作った話
HTML5 CanvasとTypeScriptでテトリス風ブロックパズルを実装した。エンジンとUIを分離するSnapshotパターンや、ネオン演出のこだわりを解説する。
ゲーム実況のサムネイル作りで学んだデザインの基本
非デザイナーがゲーム配信のサムネイルを自作し続けて気づいた、視認性・配色・構図の基本ルール。試行錯誤の記録。
配信のコメント欄が動いた瞬間の話。ゼロからイチの体験
ゲーム配信でコメントがゼロの日々を超えて、初めてリアルタイムでコメントが来た瞬間の話。ゼロからイチの体験がモチベーションを変えた。