Next.js 16.2×TS6移行のhydration mismatch修正術

Next.jsを上げた直後に、開発画面で hydration mismatch が急に増えて「どこから触ればいいんだろう」と止まること、ありますよね。この記事は、Next.js 16.2TypeScript 6.0移行を同時に進める人に向けて書いています。読むと、+ Client / - Server の差分表示を使って、原因特定から修正までを最短で回せるようになります。僕は福祉事業のIT全般を担当しながら、AI×SaaSの開発も並行していて、実務でこの手の初期表示トラブルを潰し続けています。その経験を、今日から使える形でまとめます。

公開前確認(2026年5月時点):Next.js 16.2系とTypeScript 6移行では、Hydration mismatchを型エラーだけで扱わず、SSR/CSR差分、日付・乱数、ブラウザ専用API、依存パッケージの順に切り分けてください。

こんな方におすすめ

  • Next.js 16.2へ上げたら hydration mismatch が増えた方
  • TypeScript 6.0移行で tsconfig の差分に不安がある方
  • SSR/CSRの不一致を毎回感覚で直してしまう方
  • チームで再発防止のルールまで作りたい方

この記事でわかること

  • Hydration Diff Indicator の読み方と切り分け順
  • TS6移行で不一致が顕在化しやすい理由
  • 最短で直す10項目チェックリスト
  • 再発を減らすCI・レビュー観点
僕は福祉事業のIT全般を担当しつつ、フリーランスでAI×SaaS開発も続けています。React/Next.js/TypeScriptを業務で横断しているからこそ、現場で詰まりやすいポイントを実装目線で言語化します。

Next.js 16.2のHydration差分表示とは何か(+ Client / – Serverの読み方)

2026年3月18日に公開された Next.js 16.2 で、Hydration Diff Indicator が入りました。エラーオーバーレイ上で、サーバー出力とクライアント出力の差分が + Client / - Server で並ぶので、以前より「どこがズレたか」を直接見つけやすいです。公式リリースは Next.js 16.2 の紹介ページ で確認できます。

イメージとしては、Gitの差分をUIにそのまま出してくれる感じです。結論から言うと、まず差分の“種類”を読むだけで、修正方針の8割が決まります。例えば、日時文字列のズレなら Date() 系、タグ構造のズレなら不正ネスト、要素の有無が変わるなら window 分岐や browser API 依存を疑う、という流れです。

  • 文字列だけ違うDate やロケール、乱数、翻訳タイミングを確認します
  • 要素数が違うtypeof window や条件分岐、拡張機能の注入を疑います
  • DOM構造が違う<p> 内に <div> を入れるなどの不正ネストを確認します
Next.js 16.2 では dev サーバー起動や描画も改善され、差分確認の試行回数を増やしやすくなりました。調査は「速く何回回せるか」が勝負です。

さらにこの版では Error.cause が最大5階層までオーバーレイに出るので、ライブラリ内部で起きた例外も追いやすいです。つまり「何が起きたか」を推測で埋める時間が減ります。差分を見る→原因を仮説化→最小修正で再検証 のループを、まず1日で習慣化すると強いです。

TypeScript 6.0移行で不一致が増える理由(baseUrl・moduleResolution変更の影響)

2026年3月23日の TypeScript 6.0 では、baseUrl の扱いが実質的に後退し、moduleResolution classic も終了しました。詳しくは TS 6.0 リリースノート にまとまっています。これ自体は良い整理ですが、移行時に import 解決の曖昧さが表面化し、SSR/CSRで別コードが通ってしまっていた箇所が露出しやすいです。

論点 移行前に起きがち TS6移行後の変化 Hydrationへの影響
baseUrl依存 短いimportが偶然解決 pathsを明示する流れへ 実行時経路のズレが見える
classic解決 古い探索順が残る modern前提へ統一 環境差の潜伏バグが減る
モノレポ参照 境界が曖昧 参照ルールを固定化 SSR専用/CSR専用の混入を検知しやすい

実務では、次のような差分から始めると安全です。

// before
"baseUrl": "./src",
"paths": {
  "@app/*": ["app/*"]
}

// after
"paths": {
  "@app/*": ["./src/app/*"]
}

運用メモとして、外部導線ではなく、実測ログ・設定差分・再現手順を同じ場所に残してチーム内で確認できる形にしてください。

最短で直すチェックリスト10項目(原因7分類+優先修正順)

Next公式のHydrationエラー解説は原因を7分類しています。ここに現場で効率が上がる3項目を足して、10項目チェックリストにしておくと迷いません。つまり「毎回ゼロから考えない仕組み」を作るということです。公式ページは こちら です。

  1. 不正ネスト確認<p> 内の <div> などHTML構造エラーを直します
  2. window 分岐確認 : render中の typeof window 分岐を除去します
  3. browser API確認localStorage 参照をクライアント実行へ寄せます
  4. 日時・乱数確認Date() Math.random() を初期描画から外します
  5. 拡張機能影響確認 : シークレットモードで再現性を比較します
  6. CSS-in-JS設定確認 : 公式例通りにSSR設定を揃えます
  7. Edge/CDN改変確認 : HTML minifyや変換を無効化して検証します
  8. 差分表示の行番号記録 : 修正前後でスクショを残します
  9. 修正パターン選定useEffect / dynamic ssr:false / warning抑制を選びます
  10. 再検証 : ハードリロードと別端末で初期表示を確認します

優先順位のコツ

  • 最初に「DOM構造の不一致」を潰すと、連鎖エラーが一気に減ります
  • 次に「日時・乱数」を固定すると、再現テストの精度が上がります
  • 最後に suppressHydrationWarning を検討すると、逃げ道の乱用を防げます

この順で回すだけで、調査時間が半日から1時間台に落ちるケースは珍しくないです。チーム全員で同じ順序を使うと、レビュー速度まで上がります。

差分表示を使った実戦デバッグ手順(再現→切り分け→修正→再検証)

ここからは、僕が実務で使っている30〜45分のデバッグ手順です。Next.js 16.2 は next dev の起動が約400%高速化、条件比較で Time-to-URL が約87%改善と説明されていて、試行回数を稼ぎやすいです。描画速度も実アプリで25〜60%改善の報告があるので、修正ループに向いています。

  1. 再現を固定 : ブランチを切り、エラー画面とURLを保存します
  2. 差分を分類+ Client/- Server を「文字列/要素/構造」に分けます
  3. 最小修正 : 1箇所だけ直して再起動せずに即確認します
  4. 副作用確認 : イベント発火と入力フォームの挙動を触って確認します
  5. 再発防止メモ : 原因・修正・再発条件をPRテンプレに残します
// 例: まずは原因観測を優先
console.log('server-render-value', value)
useEffect(() => {
  console.log('client-render-value', value)
}, [value])

ポイントは「一度に一つだけ変える」ことです。2つ以上を同時に直すと、どの変更が効いたかが分からなくなります。優先順位が割れたら、差分の種類ごとに担当を分けて30分で再集合する運用にすると、議論が止まりにくいです。

そのまま使える修正コード集(useEffect / dynamic ssr:false / suppressHydrationWarning / iOS対策)

公式が推奨している修正は大きく3つです。React公式でも「不一致はバグとして扱う」と明記されているので、まず正攻法で直します。suppressHydrationWarning は便利ですが、1階層のみの逃げ道なので常用はおすすめしません。

修正パターン 向いている場面 メリット 注意点
useEffectへ寄せる クライアントだけで良い表示 安全で再発しにくい 初期表示はプレースホルダ設計が必要
dynamic ssr:false 重いUI部品や外部依存 局所的に切り離せる SEO対象領域には不向き
suppressHydrationWarning 時刻など不可避差分 短期回避ができる 根本原因は残る
// 1) クライアント専用処理に寄せる
const [isClient, setIsClient] = useState(false)
useEffect(() => setIsClient(true), [])

// 2) 局所的にSSRを無効化
const NoSSR = dynamic(() => import('../components/no-ssr'), { ssr: false })

// 3) 不可避差分を抑制(1階層のみ)
<time suppressHydrationWarning />

// 4) iOS自動リンク化対策
<meta name="format-detection" content="telephone=no, date=no, email=no, address=no" />

イメージとしては、useEffect は「営業時間外の処理を後ろに回す」、dynamic ssr:false は「別レーンに流す」、suppressHydrationWarning は「一時的な注意書き」です。第一候補は常に useEffect からと覚えておくと判断が速くなります。

再発防止のCI・レビュー観点(tsconfig監査、SSR初期描画の固定化、Edge/CDN設定)

修正より大事なのは再発防止です。特にTS6移行期は tsconfig の差分が大きいので、設定監査をCIに載せるだけで事故率が下がります。僕の現場では、Node.js + TypeScript のモノレポで「初期描画は純粋関数に近づける」を合言葉にしています。

  • tsconfig監査baseUrl 依存が残っていないかPRで確認します
  • SSR固定化 : 初回描画で Date random window を使わない規約を置きます
  • Edge/CDN監査 : HTML変換・自動最適化の有効範囲を明示します
  • レビュー定型文 : 「SSRとCSRで同じ出力か」をチェック項目に入れます
# 例: CIで最低限回す項目
npm run typecheck
npm run lint
npm run test
npm run build
レビューで迷ったら「この値はサーバーで確定できるか?」を最初に聞くと早いです。確定できないならクライアント側へ寄せる、これだけで議論がシンプルになります。

運用メモとして、外部導線ではなく、実測ログ・設定差分・再現手順を同じ場所に残してチーム内で確認できる形にしてください。

TypeScript 6.0移行を後回しにした先に待つ現実

移行を先送りすると、普段は見えないズレがリリース直前に一気に噴き出す可能性があります。特に hydration mismatch は「見た目が少し違う」だけで終わらず、イベントが別要素に結びつくなどUX事故につながります。この仕組みを知らないままだと、開発速度だけでなくユーザー体験まで落ちる可能性があります。小さく直して、早く検証する習慣が結果的に一番コストを抑えます。

この記事を書いている理由

僕自身、ディズニーテーマの結婚式Web招待状サービスを継続改善して、90日以上のログイン継続率を作ってきました。初期表示で違和感が出ると、ユーザーは一瞬で離れるんですよね。だからこそ、Hydration不一致は「あとで直す不具合」ではなく「最初に潰す体験課題」だと強く感じています。福祉事業のIT全般を担当しながら、AI×SaaS開発でも同じ壁に何度も当たったので、実務で使える手順として残したいと思って書きました。

次のアクション

まずは今日、1つの画面でチェックリスト10項目を回してみてください。詰まった箇所をコメントやSNSで共有してくれたら、次の記事で具体例として深掘りします。

今日からできるアクション

  • Next.js 16.2 の差分表示で、直近エラー1件を分類する
  • TS6移行PRに「SSR/CSR一致チェック」を1行追加する
  • 運用メモとして、外部導線ではなく、実測ログ・設定差分・再現手順を同じ場所に残してチーム内で確認できる形にしてください。