← 戻る 夜の開発者のデスクに輝く琥珀色のターミナル、使い込まれたキーボードの横に空のコーヒーマグ、背景には雨に濡れた窓

Next.js 16へのアップグレード:私の実際のマイグレーションノート

3週間前、私はSeahawkのオフィスで木曜日の午後に座っていて、個人のポートフォリオサイトのNext.js 15から16へのアップグレードに40分かかるだろうと、かなり自信を持っていました。その日の残りすべてを費やしました。正直に言って、変更ログは実際に破壊される部分への準備ができていません。

この時点で12,000以上のサイトをビルドしてリリースしています。これを言うのは自慢するためではなく、これらのマイグレーションを十分に行ってきたので、公式のアップグレードガイドが何かを見落としているかどうかを知っているということです。Next.js 16は数点見落としています。そこで、ここに私の実際のノートがあります。これは、誰かが私のために書いてくれていればよかったと思う方法で書かれています。

---

そもそもなぜアップグレードしたのか

Turbopack。それが短い答えです。

より長い答えは、2つのサイトがNext.js 14に、1つはすでに15にあり、Turbopackのストーリーが展開されるのを約18ヶ月間見守ってきたというものです。バージョン16は、Turbopackがnext devでデフォルトでオンになる最初のリリースです。これは細かい話ではありません。昨年ファッションクライアント向けに行った中規模なeコマースビルドでは、開発時のコールドスタート時間は残酷でした。最初のロードで12〜18秒の話です。Turbopackが本当にそれを減らすなら、マイグレーションの苦痛に見合う価値があります。

ネタバレ:それは実際に減らします。同じクラスのプロジェクトでは、3〜4秒のコールドを見ています。これは本当です。

しかし、そこに到達するための道には鋭い端があります。

---

実際のアップグレードコマンド(および最初に実行すること)

何かに触れる前に、現在の設定の完全な監査を実行してください。私は今、npx @next/codemod@latest を厳密に使用しています。すべてをキャッチすることはできませんが、明白な名前変更と非推奨のAPI呼び出しをキャッチします。それを実行し、出力をコミットしてから、package.jsonをバージョンアップします。

アップグレード自体:

  1. package.jsonでnext、react、およびreact-domをターゲットバージョンに更新する
  2. npm installを実行する(またはpnpm installを実行する、私は2年間pnpmを使用しています)
  3. コードモッドを実行する:npx @next/codemod@latest upgrade
  4. next devを起動し、単一のコンポーネントに触れる前にすべての警告を読む
  5. コンポーネントの問題を修正する前に設定の問題を修正する。ここでは順序が重要です

コードモッドステップは、人々がつまずくのを見たところです。スキップして3つの異なるエラーに遭遇し、1時間を自動修正されるであろう事柄を追い求めるのに費やします。スキップしないでください。

---

next.config.jsの変更があなたを噛む

これは私にとって最初の本当のサプライズでした。設定APIは予想以上にシフトしました。

experimental ブロックは現在、より細いです

過去1、2年間experimentalに住んでいたいくつかのフラグは、安定版に昇格して(トップレベルに移動)またはまったく削除されています。私が個人的に遭遇した2つ:

  • experimental.appDir は廃止されました。App Router がデフォルトになりました。config に記載されていると警告が出ます(セットアップによっては直接エラーになります)。
  • experimental.serverComponentsExternalPackages は、config のトップレベルの serverExternalPackages に昇格しました。

2番目のやつは Prisma を使うサイトで引っかかりました。サーバーバンドルのビルドが静かに失敗していて、40分間も間違ったファイルを見てました。コンポーネントのせいだと思う前に、next.config.js を上から下まで確認してください。

Turbopack config は新しい場所に移動しました

カスタム Webpack config を使っていて、Turbopack に切り替える場合(デフォルトになったので切り替わります)、next.config.js の webpack() 関数は Turbopack 実行時には適用されないことを知っておく必要があります。next build の時だけ適用され、それでも Webpack を使っています。

カスタム SVG ハンドリング(私はほとんどのプロジェクトで SVGR を使う)、カスタムモジュールエイリアス、またはローダー config がある場合に重要です。新しい turbopack config ブロックで複製する必要があります。Next.js Turbopack configuration ドキュメントはこの点でかなり良くできているので、何か壊れていると思う前に一読の価値があります。

---

React 19 互換性:静かな落とし穴

Next.js 16 は React 19 をピア依存関係として搭載しています。Next.js 14 からアップグレードしている場合(15 をスキップ)、React のメジャーバージョンを一度に 2つ跳び越えることになります。ここが事態が複雑になるところです。

最大の問題は古いサードパーティコンポーネントライブラリにありました。内部で ReactDOM.render() を使っていたテーブルライブラリをクライアントサイトで使っていました。React 19 ではその API が完全に削除されました。React 18 で廃止予定でしたが、それでも機能していました。19 ではエラーになります。完全に。

火曜日の午前中をこれに費やしました。エラーメッセージはライブラリを直接指さしません。ReactDOM.render はもうサポートされていないということだけを教えてくれます。npm ls react を実行して、ツリー内のどのパッケージが React ピア依存関係の競合宣言を持っているか確認してください。このコマンドだけで、推測に 2時間費やすことが避けられました。

React 19 に特有の知っておく価値のあるパターンがいくつかあります:

  • forwardRef は ref を渡すためにもう必要ありません。ref は通常の prop になりました。forwardRef を使っている古いコンポーネントも機能しますが、廃止予定警告が表示されます。
  • use() は安定し、クライアントコンポーネント内の非同期データに実に便利です。直線的なフェッチに useEffect + state よりも use() を使い始めました。
  • Server Actions はより厳しい型要件があります。action シグネチャで緩く型付けされたものがあれば、TypeScript が今はそれを見つけます。

---

App Router:キャッシング動作の変化

これは微妙で、気をつけていないと本番環境で引っかかります。

Next.js 14 では、Server Components 内の fetch() はデフォルトで積極的にキャッシュされていました。{ cache: 'no-store' } でオプトアウトする必要がありました。Next.js 15 でこれが逆転し(fetch はデフォルトでキャッシュなし)、Next.js 16 ではさらに明確なコントロールで同じ方向を続けています。

14 から 16 に一度に移行した場合(私のサイトの 1つでそうしました)、古いデフォルトキャッシング動作に依存していたページは、すべてのリクエストでライブフェッチを開始するようになります。ページによっては大丈夫です。他のページでは API に負荷をかけてレスポンスタイムを落とします。

The fix is explicit: use export const revalidate = 3600 (or whatever interval makes sense) at the route segment level, or pass { next: { revalidate: 3600 } } directly in your fetch call. The Next.js caching documentation has a solid breakdown of what caches what and when.

fetch( に対してクイック grep を使って影響を受けたサイトのすべてのデータ取得ルートを監査し、明確なキャッシング宣言を追加しました。2時間かかりましたが価値がありました。レスポンスタイムは ~800ms の平均から修正後 ~120ms に戻りました。

---

実践における Turbopack:良い点とうっとおしい点

ぶっちゃけ言うと:Turbopack は素晴らしい。コールドスタート時間は劇的に改善されました。ほとんどの変更でホットモジュール置換がほぼ瞬時に感じられます。日々の開発では意味のあるライフスタイル向上です。

しかし荒い部分があります。

まだ機能していないもの

これらの移行を行った時点で、dev 向け Turbopack でまだ完全にサポートされていなかったものがいくつかありました:

  • Webpack 固有のローダーの一部には Turbopack の同等品がまだありません。SVGR は config 変更が必要でした(Turbopack の rules 構文は Webpack の module.rules と異なります)。
  • カスタム Babel トランスフォーム。Turbopack は SWC のみを使用します。プロジェクトに .babelrc または babel.config.js にカスタムプラグインがある場合、それらは実行されません。これは既知の制限であり、Vercel チームは Turbopack のドキュメントで明確に説明しています。
  • 一部の PostCSS プラグインの組み合わせは開発時に予期しない動作をします。Tailwind v4 とカスタム PostCSS セットアップで見かけました。修正は PostCSS プラグインの順序を明示的に固定することでした。

`--turbopack` フラグは不要になりました

バージョン 16 では Turbopack が next dev のデフォルトになったため、もう --turbopack フラグは必要ありません。バージョン 15 で試験的に使用していた package.json スクリプトにそれがあっても、問題は起きませんが、冗長です。スクリプトを整理してください。

---

TypeScript と ESLint 設定の更新

私を困らせた 2 つのハウスキーピングの問題です。

Next.js 16 は TypeScript 5.x が必須になりました。まだ TypeScript 4.x を使っているプロジェクト(古いプロジェクトもあります)の場合、別途アップグレードが必要です。他にすることを始める前に、npx tsc --version を実行してください。

ESLint 設定の状況も変わりました。Next.js 16 は ESLint 9 サポートを搭載しており、ESLint 9 は従来の .eslintrc 形式ではなくフラット設定形式(eslint.config.js)を使用します。古い形式をまだ使っている場合、Next.js は段階的に対応しますが、警告が表示されます。その際に 2 つのプロジェクトをフラット設定に移行しました。最初の摩擦を乗り越えると、本当はより洗練されています。

---

移行チェックリスト(順番通り)

このアップグレードをしているチームのメンバーに渡すものです:

  1. 何かに触れる前に、現在の設定ファイルとロックファイルをバックアップしてください
  2. Node.js バージョンを確認してください。Next.js 16 は Node 18.18 以降が必須です
  3. 現在のバージョンで npx @next/codemod@latest upgrade を実行してください
  4. package.json の next、react、react-dom バージョンを更新してインストールしてください
  5. next.config.js で昇格または削除された experimental フラグを確認してください
  6. npm ls react を実行して、サードパーティライブラリの競合を見つけてください
  7. コードベースで fetch( をグレップして、キャッシング宣言を監査してください
  8. Turbopack の同等物が必要な .babelrc または Webpack 固有のローダーを確認してください
  9. dev を起動し、コンポーネントに触れる前にすべての警告を読んでください
  10. 本番ビルドをローカルで実行してから(next build)、どこにもデプロイしないでください
  11. ステージング環境にデプロイし、完全な手動スモークテストを実施してください

最後のステップは当たり前のように聞こえます。しかし、ステージングをスキップして「小さな」アップグレードを本番環境に直接プッシュする人を見てきました。キャッシング動作の変更により、ホームページがすべてのリクエストでライブ API にヒットするのは小さなことではありません。

---

FAQ

Next.js 16 は本番環境で十分に安定していますか?

ほとんどのユースケースではそうです。dev の Turbopack への変更が最大の変化であり、本番ビルドは引き続き Webpack を使用するため、実際のデプロイ済み出力は開発体験ほど影響を受けません。キャッシング動作の変更はより大きな本番への懸念であり、これらは体系的に監査できます。

React 19に同時にアップグレードする必要はありますか?

技術的には Next.js 16 は React 18 を最小要件としてサポートしていますが、新機能(安定した use() フックと ref-as-prop の変更など)には React 19 が必要です。サードパーティの依存関係が多いプロジェクトの場合、React 19 へのアップグレードにコミットする前に互換性を確認する価値があります。React 19 アップグレードガイドは Next.js マイグレーションドキュメントと一緒に読む価値があります。

Turbopack では Webpack の設定が消えてしまいました。どうしたらいいですか?

Webpack の設定は next build 中も実行されます。開発環境では、next.config.js の turbopack キーを使用して関連部分をレプリケートする必要があります。特にファイル変換とエイリアスに関して、構文が異なります。公式 Turbopack 設定リファレンスを確認し、Webpack 設定が複雑な場合は 1~2 時間かかることを想定してください。

Turbopack は実際にはどのくらい速いですか?

テストしたプロジェクトでは、コールドスタートは 12~18 秒から 3~4 秒に短縮されました。コンポーネント変更時の HMR は 1~3 秒からほとんどの場合 200ms 未満になりました。これらはざっくりした数字で、プロジェクトサイズによって異なりますが、簡単なプロジェクト以上の規模なら差は顕著です。

---

このアップグレードの価値はあります。Turbopack の開発速度だけで、大規模な Next.js コードベースで作業する感覚が変わります。キャッシュの変更とサードパーティライブラリの互換性チェックについては目を開いて進めてください。実際の時間の大部分がここに費やされます。

一度に 1 つのサイトずつ進めてください。私もそうしました。

← 戻る