はじめに
レガシーなパッケージをやむを得なく使っているプロジェクトは多々あると思います。
業務でreact-scriptsのバージョンをメジャーアップデート(3→5)対応をしたので、その際のアプローチをまとめます。
他にもっと良い方法をご存じの方はぜひ教えてください。
1. 変更されたパッケージの調査
まずはnpm i react-scripts@5でメジャーバージョン5の中で最新のバージョンにアップデートします。
この後にビルドエラーが発生した場合、まずどのパッケージのバージョンが変わったかを調査します。
package-lock.jsonをGitで管理していればlockfile-diffを使って差分を確認できます。
git show <旧コミットハッシュ>:package-lock.json > old.json
git show <新コミットハッシュ>:package-lock.json > new.json
npx lockfile-diff old.json new.json > diff-result.txt
今回の調査で@babel/plugin-transform-runtimeが7.9.0→7.29.0に大幅アップしていることを発見しました。
2. @babel/runtimeのバージョン不一致
エラー内容
ERROR in ./src/xxx.ts
Module build failed (from ./node_modules/babel-loader/lib/index.js):
Error: Cannot find module '@babel/runtime/helpers/esm/regenerator'
原因
@babel/plugin-transform-runtimeと@babel/runtimeはセットで使うパッケージであり、バージョンの整合性をとる必要があります。
上記エラーは@babel/plugin-transform-runtimeが@babel/runtime側のヘルパーファイル(今回の場合regenerator.ts)を参照しようとしたのですが、そのファイルが存在しないため上記エラーが発生しました。
react-scriptsのバージョンアップでreact-scriptsが依存する@babel/plugin-transform-runtimeのバージョンが上がりました。ですがreact-scriptsが依存していない@babel/runtimeのバージョンは変わらなかった。そのためバージョンの不整合が発生しました。
調査手順
現在インストールされている@babel/runtimeのバージョンを確認します
npm list @babel/runtime
今回は@babel/runtime@7.27.0がインストールされていましたが、package.jsonには直接記載がありませんでした。つまり明示的にインストールをしていたわけではなく、@material-uiなどの別パッケージの依存としてインストールされていたものをreact-scripts配下のパッケージがdedupして使い回していました。
ファイルの存在を確認します
ls node_modules/@babel/runtime/helpers/esm | grep "regenerator"
regenerator.jsが存在せずregeneratorRuntime.jsしかないことを確認しました。
インストール前にファイルの存在を確認します
インストール前に対象バージョンのパッケージにファイルが存在するかを--dry-runで確認できます。
npm pack @babel/runtime@7.29.2 --dry-run | grep "regenerator"
helpers/esm/regenerator.jsが含まれていることを確認しました。
解決方法
npm i @babel/runtime@^7.29.2
@babel/runtimeはビルド後の成果物から参照されるためdependenciesに含めます(-D不要)。
3. ESLintのバージョン不一致
エラー内容
[eslint] Rules with suggestions must set the `meta.hasSuggestions` property to `true`.
`meta.docs.suggestion` is ignored by ESLint.
Rule: "@typescript-eslint/no-explicit-any"
原因
ESLintのバージョンアップにより、ルールがSuggestions(修正候補の提示)を提供する場合はmeta.hasSuggestions: trueを明示的に宣言しなければならない仕様になりました。古いバージョンの@typescript-eslint/eslint-pluginは古い書き方であるmeta.docs.suggestionを使っているためエラーになります。
調査手順
現在インストールされているバージョンを確認します
npm list @typescript-eslint
結果:
├── @typescript-eslint/eslint-plugin@2.34.0 ← プロジェクト直下の古いバージョン
└─┬ react-scripts@5.0.1
└── @typescript-eslint/eslint-plugin@5.62.0 ← react-scriptsが要求する新しいバージョン
メジャーバージョンが異なる(2系と5系)ためnpmがdedupできず両方インストールされており、ESLintが古い2.34.0のルール定義を読み込んでいました。
package.jsonの記載を確認します
cat package.json | grep "@typescript-eslint"
"@typescript-eslint/eslint-plugin": "^2.27.0"と記載されており、2.x.xの範囲でしかアップデートされないため5.62.0と競合していました。
解決方法
npm i @typescript-eslint/eslint-plugin@^5.62.0 -D
ESLintは開発時のコードチェックにしか使わないためdevDependenciesに含めます(-Dをつけます)。
おわりに
プロジェクトによってレガシーなサービスを使い続けないといけないのはつらいですが、どうしても避けられない時もあります。そのためにもバージョンの依存関係やpackage-lock.jsonの仕様、依存関係エラーの調査方法を把握しておく必要があります。
JISOUのメンバー募集中!
プログラミングコーチングJISOUでは、新たなメンバーを募集しています。
日本一のアウトプットコミュニティでキャリアアップしませんか?
興味のある方は、ぜひホームページをのぞいてみてください!
▼▼▼