😸

Next.js 15アップグレードで嵌った話

まえがき

エンジニアの恒川です。
2024年10月に Next.js 15 安定版がリリースされました。キャッシュ戦略に大きな変更があったり、 Turbopack のstableが使えるようになったりなど気になる変更内容がたくさんありました。
私が所属するチームでは Next.js 14 を使ったアプリケーション開発をしていましたが、今回の Next.js 15 リリースを受けてバージョンアップを行いました。
14 → 15へのアップグレードだったためサクッといけるだろうと思っていたのですが、いくつかハマりポイントがあり、完全にすべては解消できていないものの現在では Next.js 15 で開発をしています。
本記事ではアップグレード作業中に遭遇したエラーやその解消方法についていくつか紹介します。

実行環境

  • Next.js 14.2.18
  • Ubuntu 20.04.5 LTS (WSL2)

アップグレードコマンドがエラー

アップグレードとそれに伴うコードの自動変更をやってくれるコマンドを用意してくれているので、なにはともあれ実行します。
Next.js 15 ではcookiessearchParamsが非同期のAPIに変更になりました。
https://nextjs.org/blog/next-15#async-request-apis-breaking-change

この変更によって既存のコードはPromiseの解決を自力で行う必要が出てきますが、下記のアップグレードのためのcodemodコマンドでそのようなコードの変更が自動で行われます。

npx @next/codemod@canary upgrade latest

が、私のwsl2+ubuntu環境では下記のエラーが発生しました...

[Error: GDBus.Error:org.freedesktop.DBus.Error.ServiceUnknown: The name org.freedesktop.secrets was not provided by any .service files]

freedesktop.secrets.serviceはデスクトップ環境向けのサービスのようですが、なぜこのようなエラーが出てしまったのかは不明でした。
ヘッドレス環境で同様のエラーに遭遇された方もいるようでした。
https://github.com/vercel/next.js/issues/71535

解決方法:gnome-keyringをインストール

apt-get install gnome-keyring

Next.js 15 は関係ないですが、Dockerで同じエラーに遭遇された方がいたらしく、同じ解消方法を試したらうまくいきました。
https://github.com/moby/buildkit/issues/1078#issuecomment-577450070

なぜこれがインストールされていないとうまく動かなかったのか、よくわかっていません。

Turbopack + tailwindでcssビルドエラー

Turbopack がstableになったということで早速devサーバー立ち上げ時に使用するようにしてみました。

next dev --turbopack

するとcssのビルドエラーが出るようになってしまいました...

Invalid dangling combinator in selector at ...

開発しているアプリケーションではtailwindcssを用いてスタイリングを行っていますが、どうやら生成物のうち一部のcssセレクターが壊れてしまったようです。
なお、 Next.js 14 + TurboPack では再現しなかったためstableになったことで何かが変わったようです。

解決方法:求

同様の事象に遭遇された方もいたようですが、解消方法がまだわかっておらず、現在は Turbopack を使用せずにdevサーバーを立ち上げています。
https://github.com/tailwindlabs/tailwindcss/discussions/14751

WarningがErrorとして出るようになった

Next.js 14 で開発していた間もdevサーバーで起動したアプリはWarningを出していたのですが、 Next.js 15 にアップグレードするとそれらのWarningがErrorとして出るようになりました。
このような変更はリリースノート上で確認できず、また検索しても同様の事象に困っている人も見つけられませんでした。
devサーバー上でしか出ないとはいえErrorが出ているのはまずいので、ひとつひとつ対応していくことにしました。
以下ではそのうちいくつかを紹介します。

コンポーネントがuncontrolledからcontrolledに変更されたことによるエラー

ERROR: A component is changing an uncontrolled input of type text to be controlled.

「入力値を制御するのか・制御しないのかどちらかにして」というエラーです。
エラーの内容で調べると解説記事がいくつかヒットしますので、詳しい説明は割愛しますが、個人的には下記の記事がわかりやすかったと感じました。
https://zenn.dev/buzzkuri_tech/articles/198016c6407f70

開発中のアプリケーションではフォームコンポーネントの実装に React Hook Form のControllerコンポーネントを使用していました。
https://react-hook-form.com/docs/usecontroller/controller

このコンポーネントでcontrolledなフォームコンポーネントを実装していましたが、初期値がundefinedになっていたことでこのエラーが出ていました。

解決方法:valueの初期値を設定する

value={value ?? ""}のようにフォームのvalueの初期値を設定するように変更したところ、controlledなコンポーネントのままとなりエラーは解消しました。

コンポーネントのレンダリング中に別のコンポーネントの状態が更新されたことによるエラー

ERROR: Cannot update a component ... while rendering a different component ...

こちらももともとは React が警告していた内容で、レンダリング中に別コンポーネントの状態の変更は許されないようです。
調査したところ、 React Hook Form のControllerコンポーネントを使って実装しているフォームで、ほかのフォームの入力値によって非活性→活性を切り替えるようなコードが原因となっていました。

解決方法:活性に切り替えるとき、disabled=undefinedにする

ドンピシャなissueがあがっていました。
https://github.com/orgs/react-hook-form/discussions/10964#discussioncomment-8481087

活性状態をdisabled=falseではなくdisabled=undefinedで実装すると解消しました。
なぜfalseではなくundefinedにすると解消するのかはよくわかっていません...

まとめ

Next.js 14 → Next.js 15 へのアップグレード時にハマったポイントについて紹介しました。
紹介しきれなかった内容のうち興味深いものとして、開発環境でStrictMode中のエフェクトの挙動が変わったということもありました。
詳しく原因がわかっていない問題やまだ解決できていない問題もありますが、 Next.js 15 へのアップグレードに苦戦している方の一助になればと思います。

この記事を書いた人

恒川 雄太郎
2021年キャリア入社
私は普段マスクをして勤務していますが、いつニンニクたっぷりのペペロンチーノを食べても悟られないようにするためです。

FORCIA Tech Blog

Discussion