忙しい人向け
yarn 経由で pnpm コマンドを実行すると、yarn のレジストリ (registry.yarnpkg.com) が npm_config_registry として引き継がれます。
この状態で pnpm install --prefer-offline を実行すると、npm_config_registry が registry.npmjs.org でないことが原因で、tarball URL が lockfile に記録されてしまいます。
解決策は --registry=https://registry.npmjs.org を明示的に指定することです。
はじめに
モノレポの一部サブパッケージを yarn から pnpm に移行する作業をしていました。
pnpm install 単体では問題なく動いていたのに、全体インストールコマンドを実行すると pnpm-lock.yaml に謎の差分が出るという問題にハマったので、原因と解決策をまとめます。
環境・構成
- yarn v1
- pnpm v10
モノレポのルートは yarn で管理しつつ、一部のサブパッケージだけ pnpm に移行した構成です。
/ (root) ... yarn
client/foo/ ... yarn
client/bar/ ... yarn
client/baz/ ... pnpm ← 移行済み
全体インストールは root の package.json にスクリプトをまとめていました。
{
"scripts": {
"install-prefer-offline-all": "yarn install --prefer-offline && run-s install-prefer-offline:baz ...",
"install-prefer-offline:baz": "cd client/baz && pnpm install --prefer-offline"
}
}
yarn run install-prefer-offline-all を実行することで、yarn 管理のパッケージも pnpm 管理のパッケージも一括インストールできる設計です。
問題: lockfile に毎回差分が出る
yarn run install-prefer-offline-all を実行すると、client/baz/pnpm-lock.yaml に以下のような差分が出ます。
- resolution: {integrity: sha512-xxxx==}
+ resolution: {integrity: sha512-xxxx==, tarball: https://registry.npmjs.org/@emnapi/core/-/core-1.9.2.tgz}
tarball フィールドが追加される差分です。しかも pnpm install を単体で実行すると差分は出ません。yarn run 経由のときだけ起きます。
原因の調査
最初に疑ったこと: --prefer-offline のあるなし
pnpm 移行時は pnpm install(--prefer-offline なし)で lockfile を作成していました。差分が出るのは yarn 経由の pnpm install --prefer-offline を実行したときです。
「lockfile 生成時と実行時で --prefer-offline の有無が違うのが原因では?」と思ったのですが、直接 pnpm install --prefer-offline を実行しても差分は出なかったので、--prefer-offline は関係ありませんでした。
本当の原因: yarn が npm_config_registry を書き換えていた
yarn run でスクリプトを実行すると、yarn は自身の設定を環境変数として子プロセスに注入します。
そのひとつが npm_config_registry で、yarn のデフォルトレジストリである registry.yarnpkg.com がセットされます。
# yarn run 経由で実行すると環境変数がこうなっている
npm_config_registry=https://registry.yarnpkg.com
pnpm はこの環境変数を参照するため、yarn 経由で呼ばれた pnpm は registry.yarnpkg.com からパッケージを解決しようとします。
なぜ tarball URL が lockfile に記録されるのか
詳細な仕組みは追いきれていませんが、npm_config_registry が registry.npmjs.org でない状態で pnpm install --prefer-offline を実行すると tarball URL が lockfile に記録される、という現象が確認できました。
| 実行方法 | npm_config_registry | tarball の記録 |
|---|---|---|
pnpm install 単体 |
registry.npmjs.org | なし |
yarn run 経由の pnpm install
|
registry.yarnpkg.com | あり(差分が出る) |
これが差分の正体でした。
解決策
pnpm install に --registry=https://registry.npmjs.org を明示的に追加します。
- "install-prefer-offline:baz": "cd client/baz && pnpm install --prefer-offline",
+ "install-prefer-offline:baz": "cd client/baz && pnpm install --prefer-offline --registry=https://registry.npmjs.org",
yarn 経由で実行しても参照レジストリが registry.npmjs.org に固定されるので、lockfile に不要な tarball URL が記録されなくなります。
おわりに
- yarn 経由で pnpm を呼ぶと
npm_config_registryがregistry.yarnpkg.comになる - pnpm はデフォルトレジストリ以外を使うと tarball URL を lockfile に記録する
-
--registryを明示指定することで回避できる
yarn と pnpm を混在させる場合、yarn が環境変数を通じて意図せず pnpm の動作に影響を与えることがあります。同じ構成で困っている方の参考になれば幸いです。