yarnをcorepack管理とclassic(v1)が使われているプロジェクトで自動的に使い分ける
yarn v4がリリースされました
ちょっと前に知ったんですがyarn v4が10月23日に正式リリースされていました。
前にyarn v4からはバンドルされたJavaScriptプログラムであるreleasesやpluginsをGitにコミットする必要が無くなります - ncaqという記事を書きました。
この記事に書いてある通り、 yarn v4ではyarn berry(v2以後)に感じていた問題が解決されていました。その時v4が正式リリースされたら移行しようと考えていたため移行します。
その時に少しだけ躓いた問題をメモします。
勝手にプロジェクトがマイグレーションされてしまう問題
私は~/.local/bin
をPATH
に追加してユーザスペースでインストールするプログラムはそこに置いてあるので、
corepackでインストールする場合以下のようなコマンドを実行します。
corepackはNode v14から追加されています。
corepack enable --install-directory ~/.local/bin npm yarn
私はGentoo LinuxのnodejsのUSEフラグで、 corepackを有効にして競合するnpmのUSEフラグを無効化しているため、 npmもcorepack管理しています。 pnpmとかも有効化出来ますがとりあえず今は使ってないのでスルーしています。
しかしyarn v3の頃は問題なかった気がするのですが、この方法でcorepackでプロジェクトに依存しないグローバルにインストールしてyarn
コマンドを使うと、そのプロジェクトがyarn classic(yarn v1)で管理されていると自動でyarn v4にマイグレーションされてしまいます。
自分のプロジェクトなら流石にそろそろberryに移行するのでそれを機会にマイグレーションしても良いのですが、他人がGitHubにホストしてるプロジェクトにちょっとしたPRを出すときに、「ついでにyarn berryに移行しておきました」と出すのは流石に気が引けます。
理想の動きとしてはberry移行しているプロジェクトでは指定されたバージョンのパッケージマネージャを使って、 yarn classicを使っているプロジェクトではyarn classicを使うようにしたいです。
corepackを使わずyarnパッケージを使うのはダメ
ではcorepackを使うのをやめて、 Gentooが提供するyarnパッケージを使えば良いのではと考えました。
yarn v1は、 yarn v2にまつわる誤解 | Wantedly Engineer Blogに書かれてあるように、新しいyarnのブートローダとして使えます。今それをcorepackとして分離していて一応corepackはまだExperimentalなのでそれでも良いかなと考えました。
しかしそれはそれで問題があります。
corepackで管理されていると、 corepack is 何?に書かれてあるように、 package.jsonに、
"packageManager": "yarn@4.0.1"
のように書いてあれば自動でyarn v4が使われるのですが、 yarnのブートローダ機能に頼る場合はそれは使えません。
その場合、 .yarnrc.ymlに、
yarnPath: .yarn/releases/yarn-4.0.1.cjs
のように書かれてそれが読み込まれることになるのですが、そうなると.yarn
ディレクトリを消すとyarnが実行できなくなってしまうため、先の私の記事で書いたようにバンドル済み実行プログラムをgitにcommitする必要が発生してしまいます。
corepackでグローバルにはyarn classicをインストールする
これの解決方法は簡単です。
corepackを使ってグローバルにはyarn classicをインストールして、プロジェクトごとにパッケージマネージャをyarn set version stable
などで指定すれば問題ありません。
具体的には以下のようにします。
# corepackでnpmとyarnを管理する。
corepack enable --install-directory ~/.local/bin npm yarn
# グローバルでは勝手にマイグレーションを行わないようにyarn classicを利用する。
corepack prepare yarn@1 --activate
自分はこれをyarn-install-world
実行スクリプトに含めて、
yarn global add
でprettierをインストールするついでに事前実行しています。
これでyarn classicが使われているプロジェクトではyarn classicが使われ、 corepackでパッケージマネージャを管理しているプロジェクトではそれが使われるようになりました。