
Next.js(特に App Router)は便利な反面、**「あれ?なんでエラー?」**という落とし穴も多いフレームワークです。
この記事では初心者〜中級者がよくつまずくポイントを 4つに厳選して、分かりやすく解説します。
- App Router で “use client” が必要か判断する基準
- 動的ルートで hydration error が出る時の対処法
- 画像アップロード時にバンドルが肥大化する原因
- Edge Runtime と Node.js Runtime の違い
Next.js を使った開発で悩んだら、ここをチェックすればほぼ解決できます。
Contents
1. App Router で “use client” が必要かどうか判断する基準
App Router では、デフォルトがサーバーコンポーネントです。
そのため、ほんの少しでもクライアント側の処理が混ざるとエラーになります。
🔍 “use client” が必要になる条件まとめ
| 条件 | 説明 |
|---|---|
| ブラウザAPIを使う | window localStorage document など |
| React Hooks を使う | useState useEffect useRef など |
| ユーザー操作が必要 | ボタンで動く処理、フォーム入力など |
| アニメーション・モーダル | Framer Motion などブラウザ依存のUI |
これらが1つでも当てはまる場合は、ファイルの先頭に
"use client";
を付けましょう。
❌ “use client” を付けなくて良いケース
| 付けなくてOK | 理由 |
|---|---|
| データ取得だけのコンポーネント | サーバー側で完結するため |
| API から取得した情報を表示するだけ | SSRで十分対応できる |
| Layout や metadata の設定 | すべてサーバーコンポーネントでOK |
💡 基本ルール(覚え方)
「ユーザーが触るなら client」「読ませるだけなら server」
これを覚えておくと判断が非常にラクになります。
2. 動的ルートで Hydration Error が出るときの対処法
Next.js のエラーで最も多いのが hydration error(ハイドレーションエラー)。
特に /user/[uid] や /post/[id] など 動的ルートで発生しやすいのが特徴です。
🔥 Hydration Error が起きる代表的な原因
- サーバー側とクライアント側で表示がズレる
- 日付のフォーマット
- ランダム値(
Math.random()) - 初期描画で undefined → 後から値が入る UI
- 動的パラメータをクライアント側で誤って取得している
useEffectの結果とサーバー側の値が不一致
- 非同期読み込みの結果がタイミングで変わる
✔ 対処法(最重要)
(1) サーバー側で値を確定させる
App Router では 非同期 Server Component が使えるため、
export default async function Page({ params }) {
const data = await fetch(...);
return <UI data={data} />;
}
のように 初期描画段階でデータを確定させるのが最も安全です。
(2) クライアント側で値が変わる処理はプレースホルダーを使う
{profile ? <ProfileCard /> : <LoadingSkeleton />}
こうすると React が描画差分を正しく扱えるため、ズレが出ません。
(3) ランダム値・日時はサーバー側で固定
new Date().toLocaleString()
これをクライアントとサーバーで実行すると 100%ズレます。
3. 画像アップロード時にバンドルが肥大化する原因
Next.js + 画像アップロードの実装でよくあるのが、
- ビルドが重い
- バンドルサイズが急に肥大化
- デプロイが遅い
という問題です。
原因は主に以下の通り。
🧨 原因1:画像処理ライブラリをクライアントに含めている
例
sharpjimpbrowser-image-compressionreact-image-cropなど
本来サーバーで実行すべきロジックが、クライアント側に流れると
バンドルサイズが数MB〜数十MBに膨れ上がることも。
✔ 対処法
(1) 「画像処理」はサーバーに寄せる
Next.js App Routerでは Route Handler が使えるため、
/api/upload/api/resize-image
などをサーバー側に作り、そちらに処理を集約します。
(2) 画像読み込みは <Image /> を使う
Next.js の Image コンポーネントは 最適化済みで、
自動的に軽量化・遅延読み込みされるためバンドル肥大化を防げます。
(3) データURL (base64) を肥大させない
base64は ファイルサイズが約33%増えるため、
そのまま保存すると重くなりやすいです。
→ 必ず Storage や S3 にアップロードし、URL だけ Firestore に保存しましょう。
4. Edge Runtime と Node.js Runtime の違い(初心者向けの最速理解)
✨ 結論から
Edge Runtime:超高速・軽量だけど制約多い
Node.js Runtime:自由度が高く、ほぼなんでも動く
この理解でOKです。
🧩 Edge Runtime(Cloudflare Workers のような動作)
- 非常に高速
- グローバルにキャッシュされる
- 起動コストが低い
- Cold Start がほぼゼロ
- ただし制約が多い(
fs、crypto.randomUUID()など使えない)
Next.js の例:
export const runtime = "edge";
用途:
- 軽いAPI
- 認証チェック
- レスポンス高速化が重要な処理
🧩 Node.js Runtime(従来のサーバー)
- とにかく自由度が高い
- Firebase SDK、stripe、image処理などほぼ全部動く
- バックエンド向き
- 速度はEdgeほどではないが十分速い
Next.js の例:
export const runtime = "nodejs";
用途:
- 画像アップロード
- Firestore / Storage の書き込み
- 重いサーバー処理
- 外部API統合
まとめ|Next.js は理解すれば怖くない
今回紹介した落とし穴は、Next.js App Router で特に起きやすいトラブルです。
- “use client” はユーザーが触る時だけ
- Hydration Error はサーバーとクライアントの差分が原因
- 画像アップロードはサーバー側に寄せるのが正解
- Edge Runtime と Node.js Runtime は速度と自由度で住み分ける
この4つを押さえておくと、Next.js の開発が一気にスムーズになります。









