Open3

Next.JSをv15に更新する

LeivyLeivy

バージョンの更新

まずは公式がアナウンスしているコマンドをそのまま実行してみる

$ npx @next/codemod@canary upgrade latest
Need to install the following packages:
@next/codemod@15.0.1-canary.3
Ok to proceed? (y) y
npm WARN deprecated inflight@1.0.6: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
npm WARN deprecated rimraf@2.6.3: Rimraf versions prior to v4 are no longer supported
npm WARN deprecated glob@7.2.3: Glob versions prior to v9 are no longer supported
npm WARN deprecated cross-spawn-async@2.2.5: cross-spawn no longer requires a build toolchain, use it instead
  Detected installed versions:
  - React: v18.3.1
  - Next.js: v14.2.15
Upgrading your project to Next.js 14.2.16...

なぜか14.2.15への更新が始まってしまいました。
執筆時点(2024年10月23日)では、まだnpmパッケージに反映されていないのでしょうか。

とりあえずバージョンを明示的に指定してみることに

# 成功!
$ npx @next/codemod@canary upgrade 15.0.1
  Detected installed versions:
  - React: v18.3.1
  - Next.js: v14.2.16
# ターボパックをしようるすかどうか。今回はYesで設定
✔ Enable Turbopack for next dev? … yes
? The following codemods are recommended for your upgrade. Select the ones to apply. ›  
Instructions:
    ↑/↓: Highlight option
    ←/→/[space]: Toggle selection
    a: Toggle all
    enter/return: Complete answer
◉   (v15.0.0-canary.179) app-dir-runtime-config-experimental-edge
               Transform App Router Route Segment Config `runtime` value from `experimental-edge` to `edge`(v15.0.0-canary.171) next-async-request-api
◉   (v15.0.0-canary.153) next-request-geo-ip
◉   (v15.0.0-canary.44) next-dynamic-access-named-export

何やら選択肢がいろいろ表示されています。まずは上から順番に何なのか知りましょう。

  • app-dir-runtime-config-experimental-edge: appディレクトリでruntime設定にexperimental-edgeを使っているなら選択するべきです。使っていないなら不要です。

  • next-async-request-api: 非同期リクエスト(例: API Routesでasync関数を使っている場合)を使っているなら、このcodemodは新しい仕様に対応するために重要です。そうでなければ不要です。

  • next-request-geo-ip: Geo-IP(ユーザーの地理的位置に基づいて処理を分ける機能)を利用している場合、これも新しい仕様に適応するために選択するべきです。使っていないなら不要です。

  • next-dynamic-access-named-export: next/dynamicで名前付きエクスポートを動的インポートしている場合は選択するのが良いです。特に動的インポートを使っていない場合は選択不要です。

この中から自分のプロジェクトに最適なオプションを選択して次に進みます
今回アップデートするプロジェクトではnext-async-request-apiしか当てはまらなかったので、それ以外のハイライトはスペースキーで解除して、エンターキーを押します

操作方法

  1. 上下キーで選択肢を移動

    • またはキーを使って、選択肢を上下に移動できます。
    • これにより、適用するcodemodを選ぶためのハイライトを動かせます。
  2. スペースキーで選択/解除

    • 選択肢がハイライトされた状態で、[Space]キーを押すとそのcodemodが選択されます。
    • もう一度[Space]キーを押すと、その選択が解除されます。
  3. aキーで全選択/全解除

    • aキーを押すと、すべてのcodemodを一括で選択または解除できます。
    • 全選択したくない場合は、再度aキーを押すことで全解除できます。
  4. Enterキーで確定

    • すべての選択が完了したら、Enterキーを押して選択内容を確定します。
    • これにより、選択したcodemodが適用されます。

  • 必要なcodemodをハイライト(↑/↓)で移動して選び、[Space]キーで選択。
  • 必要なものをすべて選んだら、Enterキーで確定して進みます。

次に、以下の選択肢に回答する

# React 19へのアップグレードに必要なコード変更を自動的に行い、Reactの最新仕様に対応させるcodemod
✔ Would you like to run the React 19 upgrade codemod? … yes
# TypeScriptを使用している場合、React 19の新しい型定義に合わせてコードの型変更を行うcodemod
✔ Would you like to run the React 19 Types upgrade codemod? … yes

すると何やらエラーになりました

[Error: ENOENT: no such file or directory, scandir '/home/user/.codemod'] {
  errno: -2,
  code: 'ENOENT',
  syscall: 'scandir',
  path: '/home/user/.codemod'
}
Error: Command failed: pnpx codemod@latest react/19/migration-recipe --no-interactive
    at checkExecSyncError (node:child_process:890:11)
    at execSync (node:child_process:962:15)
    at runUpgrade (/home/leivy/.npm/_npx/6a090669e21b4303/node_modules/@next/codemod/bin/upgrade.js:267:38)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async Command.<anonymous> (/home/leivy/.npm/_npx/6a090669e21b4303/node_modules/@next/codemod/bin/next-codemod.js:51:9) {
  status: 1,
  signal: null,
  output: [ null, null, null ],
  pid: 961090,
  stdout: null,
  stderr: null
}

エラーメッセージを読むと、ユーザーディレクトリに.codemodというディレクトリーが見つからない為に発生しているようです。
次のコマンドで.codemodディレクトリーを作成します。
userの部分は適切に置き換えてください。

$ mkdir /home/user/.codemod

ディレクトリーを作成したら一度バージョンを更新する前の状態に戻し、再度以下のコマンドを実行します

$ npx @next/codemod@canary upgrade 15.0.1

するとこんどは以下のエラーになりました

Error: libsecret-1.so.0: cannot open shared object file: No such file or directory 

Codemod CLI uses "keytar" to store your credentials securely. 
Please make sure you have "libsecret" installed on your system. 
Depending on your distribution, you will need to run the following command 
Debian/Ubuntu: sudo apt-get install libsecret-1-dev 
Fedora: sudo dnf install libsecret 
Arch Linux: sudo pacman -S libsecret 

これは、libsecret というライブラリがシステムに存在しないため、keytarというツールが動作できないというエラーのようです。
keytarは、CLIでの認証情報管理に使用されていますが、これが原因で問題が発生しています。

React 19のインストールは無事に成功しているので、最後に環境に合ったコマンドでlibsecretをインストールします

$ sudo apt-get install libsecret-1-dev

以上で更新完了のはずです。
あとは発生したエラーを対処して動作確認してみます。

LeivyLeivy

依存関係のエラーついて

筆者の環境ではスタイリングシステムにvanilla-extractを使用していましたが、そのまま使用するとコンパイル時に以下のようなエラーが発生しました

 ⨯ Error: Styles were unable to be assigned to a file. This is generally caused by one of the following:

- You may have created styles outside of a '.css.ts' context

当然ですがまだ対応されていないようなので、実際に運用するのはもう少しだけ様子を見ようと思います