はじめに
この記事はテスト中に遭遇した表題のエラーの、原因と解決方法を記録/するためのものです。
先に結論だけ
- npm v7で破壊的な変更が導入されました。
-
peerDependencies
のバージョン解決がより厳密になりました。 - 上流モジュールの
peerDependencies
を修正すると解決します。 - 上流モジュールの修正が出来ない場合、npm installに
--legacy-peer-deps
オプションをつけると解決します。
再現条件と手順
問題が発生する条件は以下の通りです。
- テストにはTravis CIを利用している
- 環境はnode.js
- node.jsバージョン16をテスト対象に加えた
- バージョン16のテストのみ失敗する
並列でバージョン12と14のテストも行っていますが、そちらはエラーが発生しません。
環境
Travis CIから出力される環境情報は以下の通りです。
$ node --version
v16.3.0
$ npm --version
7.15.1
$ nvm --version
0.37.2
$ yarn --version
1.22.4
エラーログ
出力されたエラーログは以下の通りです。
npm install
npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree
npm ERR!
npm ERR! Found: jest@27.0.4
npm ERR! node_modules/jest
npm ERR! dev jest@"^27.0.4" from the root project
npm ERR! peer jest@"^27.0.0" from ts-jest@27.0.3
npm ERR! node_modules/ts-jest
npm ERR! dev ts-jest@"^27.0.3" from the root project
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! peer jest@"^26.4.2" from fake-mouse-event@0.0.4
npm ERR! node_modules/fake-mouse-event
npm ERR! dev fake-mouse-event@"https://github.com/MasatoMakino/fake-mouse-event.git" from the root project
npm ERR!
npm ERR! Fix the upstream dependency conflict, or retry
npm ERR! this command with --force, or --legacy-peer-deps
npm ERR! to accept an incorrect (and potentially broken) dependency resolution.
原因
この問題の原因は、npm v7の変更です。
https://github.com/npm/rfcs/blob/latest/implemented/0025-install-peer-deps.md
npm v7ではpeerDependenciesの挙動が変更されました。npm v6以前では、peerDependenciesはあくまでユーザーに対するヒントでしかありません。パッケージの依存関係を解決したり、インストールしたりという機能はありませんでした。v7から、peerDependenciesに指定したパッケージを自動でインストールするようになりました。
その結果、npm v7はpeerDependenciesのセマンティックバージョニングを厳密に解釈するようになりました。dependenciesやdevDependenciesに、peerDependenciesと矛盾するバージョンのパッケージがインストールされていると、npm v7は依存関係の解決に失敗したとしてインストール時にエラーを返します。
node.jsのv12やv14のテスト環境でこの問題が発生しなかったのは、npmのv6を使用しているためです。
解決方法
解決方法は以下の2つです。
上流モジュールの修正
もしあなたが上流モジュールを修正できる場合、上流モジュールのpeerDependenciesフィールドを修正しましょう。
今回のエラーは自作した上流モジュールに、以下のpeerDependenciesを設定していたため引き起こされました。
"peerDependencies": {
"jest": "^26.4.2",
}
この設定を残したまま、下流リポジトリのjestをv27に更新すると、依存関係の解決に失敗してエラーが返ります。
"peerDependencies": {
"jest": ">=26.4.2 <28.0.0"
}
上流モジュールがjest v27で正常に動作するかテストし、バージョンの範囲を広げます。
--legacy-peer-deps
オプション
上流モジュールの修正が不可能な場合、npm installコマンドに--legacy-peer-deps
オプションをつけましょう。このオプションはpeerDependenciesの依存解決をv6以前と同じ処理にします。
Travis CIの場合、travis.ymlのinstallオプションを省略すると、デフォルトでnpm install
が挿入されます。オプションをつける場合は、installを明示的に指定する必要があります。
▼travis.yml
install:
- npm install --legacy-peer-deps
以上、ありがとうございました。