始めに
npm 7が公開されました。
古いバージョンのnpmとの違いはいくつかありますが、大きな点はpeer dependencyへの対処法です。
React Nativeでjestを用いてテストを記載しようとしたところ、peer dependencyの依存関係が解決できず、いろいろ調べたのでまとめました。
状況
npm installをしていると以下のようなエラーが出ることがあります。
エラーの理由
一言で言うと、「同じモジュールを違うバージョンでインストールしようとしている」ためです。
そもそもpeer dependencyとは、簡単にいうと「依存関係はあるけど、バージョン指定はインストールする人が自分のプロジェクトに適切なものを選んでね」というものです。
以下の記事に詳しく載っています。
Understanding Peer Dependencies in JavaScript
私たちが、モジュールをインストールする際、npmはそのモジュールを動かすために必要なモジュールも一緒にインストールしてくれます(依存関係の解消)。
しかし、いくつかモジュールをインストールしていると、Aモジュールで使うCモジュール、Bモジュールで使うCモジュール、、、と言うように別々のモジュールが同じモジュールを依存関係に持つことがあります。
Cモジュールがpeer dependencyである、すなわち、インストール者にバージョン管理が任されている場合、Aモジュールで使用しているCモジュールのバージョンと、これからインストールしようとするCモジュールのバージョンが異なると、npmは上記のようなエラーを表示することがあります。
エラーを表示することがある、と言うのは、これがnpm 7からの仕様であるためです。古いバージョンのnpmですと、デフォルトでpeer dependencyによる不適当な依存関係を無視してしまいます。
解決策
無理やり解決したい場合は、--forceや--legacy-peer-depsオプションを使用することで可能です。
--forceは、コンフリクトを無視して強制インストールをさせるオプション。
----legacy-peer-depsは、peer dependencyを完全に無視してインストールさせるオプション。
npm4~6の挙動と同じです。
しかしこれでは依存関係を正しく処理できてはいません。
面倒ですが、手動でモジュールのバージョンを揃えることが推奨されています。
上記だと、root projectのreactはバージョン16.13.1であるのに対し、インストールしようとしているreact-test-rendererが使用するreactは17.0.2であるため、エラーとなっています。
私の場合、以下のようにバージョンを指定してインストールすることで解決しました。
react-test-renderer@16.13.1というバージョンに指定したのは、エラー文面を見る限りreact-test-rendererと、そのサブモジュールであるreactのバージョンが等しかったためです。そのため、react-test-rendererのバージョンをroot projectのreactとバージョンを一致させてインストールしました。