English

alt

Next.jsのApp Routerに移行したものの、「思った通りに動かない」「ビルドは通るのに挙動が違う」と感じたことはないでしょうか。

Pages Routerとは設計思想が大きく異なり、Server Components・キャッシュ戦略・レイアウト構造など、多くの概念が刷新されています。公式ドキュメントでは整理されていますが、実運用に落とし込むと予想外の落とし穴が存在します。

本記事では、App Routerで実際にハマりやすいポイントを体系的に整理し、原因・メリット・デメリット・具体的な対策まで丁寧に解説します。Next.jsを安定運用したい方にとって、再現性ある実装の指針になる内容です。


App Routerとは何が変わったのか

App Routerは、Next.js 13以降で導入された新しいルーティング方式です。

主な特徴

  • Server Componentsがデフォルト
  • layout.tsxによる階層レイアウト
  • fetchのキャッシュ戦略が明示的
  • Streaming対応
  • Route Handlersの導入

メリット

  • パフォーマンス向上(不要なクライアントJS削減)
  • レイアウトの再利用性向上
  • データ取得の統一的管理

デメリット・注意点

  • キャッシュ挙動が直感的でない
  • Client/Server境界の理解が必須
  • 既存ライブラリが未対応の場合あり

実際に触ると「なぜ更新されないのか」「なぜuseEffectが使えないのか」といった疑問に直面します。


Server Componentsでハマるポイント

App RouterではコンポーネントはデフォルトでServer Componentになります。

よくある問題

  • useStateやuseEffectが使えない
  • windowオブジェクト参照でエラー
  • onClickが動作しない

原因

Server Componentはサーバー側でレンダリングされ、クライアントJSを含まないためです。

解決策

  • インタラクションが必要な場合は "use client" を先頭に記述
  • ServerとClientを責務分離する
  • ロジックをServer側に寄せる設計へ変更

実運用の観察

「とりあえず全部use clientにする」実装は、パフォーマンス劣化の原因になります。最小限のClient化が重要です。

Server/Client設計の考え方についてはこちらの記事で詳しく解説しています。
/dev/server-client-boundary-guide


fetchキャッシュ戦略でハマる理由

App Routerではfetchはデフォルトでキャッシュされます。

起きやすい問題

  • データが更新されない
  • ISRが思った通り動かない
  • revalidateが効かない

キャッシュ制御の種類

  • cache: "no-store"
  • next: { revalidate: 60 }
  • revalidateTag()
  • revalidatePath()

メリット

  • パフォーマンス向上
  • CDN最適化

デメリット

  • 更新反映が遅れる
  • 開発時に混乱しやすい

具体的対策

  • 管理画面系は no-store
  • メディア記事は revalidate
  • 動的データはタグベース更新

特にVercel環境ではEdgeキャッシュとの兼ね合いもあるため、キャッシュ戦略を明確に設計することが重要です。

キャッシュとSEOの関係についてはこちらの記事で詳しく解説しています。
/ai/nextjs-cache-seo-strategy


layout.tsx設計の落とし穴

App Routerの最大の特徴は階層レイアウトです。

よくある問題

  • 子ページでレイアウトが再描画されない
  • メタデータが上書きされない
  • グローバルCSSの影響範囲が不明確

原因

layoutは一度レンダリングされると再利用されるため、状態管理の設計が重要になります。

対策

  • レイアウト内で状態を持たない
  • ページ固有データはpage.tsx側に持たせる
  • metadataはexport形式で明示

実体験的考察

レイアウトを肥大化させると保守性が低下します。責務分離を徹底することで可読性と再利用性が向上します。


Route Handlersで混乱するポイント

API Routesの代わりにRoute Handlersが導入されました。

ハマりやすい点

  • POSTが動かない
  • body取得方法が違う
  • Edge Runtimeとの違い

注意点

  • RequestはWeb標準API
  • await request.json() が必要
  • Node APIが使えない場合あり

具体的アクション

  • Node依存処理は runtime = "nodejs" を明示
  • Edgeで動かす必要があるかを設計段階で判断

動的ルーティングとgenerateStaticParamsの誤解

起きやすい問題

  • 404になる
  • 静的生成されない
  • ビルド時にエラー

理解すべき点

  • generateStaticParamsはビルド時のみ実行
  • 動的レンダリングと静的生成は排他的

対策

  • 更新頻度が高いならSSR
  • 固定記事なら静的生成+revalidate

まとめ:App Routerを安定運用するために

App Routerでハマる原因は、設計思想の変化を理解せずに従来の書き方を続けてしまうことにあります。

要点整理

  • Server/Client境界を明確にする
  • キャッシュ戦略を設計段階で決める
  • レイアウトを肥大化させない
  • Route HandlerのRuntimeを理解する
  • 静的生成と動的生成を混同しない

今すぐできる行動

  1. 既存ページのfetchにキャッシュ指定があるか確認する
  2. 不要な "use client" を削減する
  3. layout.tsxの責務を見直す

App Routerは難しいという印象を持たれがちですが、設計を整理すれば非常に強力なアーキテクチャです。理解を深めることで、パフォーマンスと保守性の両立が可能になります。

App Routerは難しく見えても、構造を理解すれば驚くほど整理され、今このタイミングで設計を見直すことが長期運用の安定化につながります。

関連記事