pnpmで意図しないpeer dependenciesがあり問題が起こるときの対処

※この情報はpnpm@9時点での情報です

tl;dr

  • pnpm i --resolution-only
  • pnpm i --fix-lockfile

peer dependenciesで問題が起こったら、どちらかを実行する。


pnpmを使っているプロジェクトで、node_modulesの中に不必要なモジュール(optional peer dependencies)がずっと入っていたりする問題がある。

このことで普通はそんなに問題は起こらないが、稀に問題を引き起こすことがある。

昔入ってしまったpeer dependenciesがnode_modules内に存在することで

こういったことが起こる。

  • import.meta.resolve でモジュールがあると誤検知してしまう
    • 入れた覚えも入っている前提でもないのに、たしかにいる!
  • TSが型解決するときにpeerのバージョンを先に見つけて古い型を使うことでエラーになる

少なくとも自分が観測した事例だと以下のようなことがあった。

  • storybookをセットアップすると less sass sugarcss などが入っている
  • viteのプラグインを入れると rollup@2 rollup@3 など過去のバージョンが入っている
    • プロジェクト環境では rollup@4 を期待するが、TSがrollup@3を見に行きプラグインが型エラーになる

ちなみに

前提としてこの問題はpnpmの hoistauto-install-peers をenableにしていると発生するはず。

両者とも.npmrcで設定しない限りデフォルトではtrue。

peer dependenciesを整理整頓する

pnpmは通常の pnpm install では一度ロックファイルに書き込まれたpeer dependenciesのバージョンは更新しない(これはpnpmではfull resolutionという概念らしい)。そしてpnpm-lock.yamlに書かれている以上は、そのバージョンのそのモジュールがインストールされてしまう。

トレードオフとして、pnpm-lock.yamlに書き込まれた「昔入れたモジュールに付随していたpeer dependenciesが更新されていない」ということが発生する。

というわけで、full resolutionする

以下のどちらかをすればよい。そしてロックファイルが更新されたあとにもう一度 pnpm iを実行して node_modules を更新する。

  • pnpm i --resolution-only
  • pnpm i --fix-lockfile

これでlockファイルがメンテされ、このエントリで言っている問題を回避できるようになる(可能性がある)。

※なおpnpmのソースコードはこのあたり