🪺

yarn v1 から pnpm への移行でより高速で安全に

2024/10/17に公開

AI Shift には yarn v1 を使って管理しているフロントエンドのモノレポがありました。しかし、インストールが遅かったり、yarn v1が2020年からメンテナンスモードでいつEOLになってもおかしくない状況なので、yarn をバージョンアップするか、npm か pnpm に乗り換える必要がありました。

技術選定

まず yarn のバージョンアップを考えましたが、yarn はv2から node_modules を使わないPnP方式を採用していて、対応していないライブラリがあったり、PnP採用に関する情報が少なかったりと不安材料が多かったので今回は yarn を採用しないことにしました。

https://yarnpkg.com/features/pnp

そうなると npm か pnpm のどちらかになります。pnpm のメリットとして package.json に書いてあるパッケージのみimportを許容する厳格性があります。 npm, yarn では深い依存を含めたすべてのライブラリが node_modules に格納されます。その結果、開発コードは package.json に書かれていない依存ライブラリにアクセスできてしまいます。

私たちのフロントエンドは巨大で多くのライブラリに依存しているので、この厳格性は大きなメリットだと感じました。

さらに pnpm v9.5 で追加されたパッケージでバージョンを揃えられるcatalog機能にも惹かれて pnpmを採用することにしました。

https://pnpm.io/ja/motivation

pnpm の環境構築

移行当初、pnpm の管理は corepack でやろうと思っていました。しかし、corepack が Node.js から分離 されることになりました。corepack が Node.js から分離されるのであれば、あえて corepack を使う必要はなくなります。

そんな中、pnpm 9.7 から package.json の packageManager に pnpm のバージョンを指定できるようになりました。 これによってチームメンバーのローカル環境、CI環境でpnpmのバージョンを揃えることができます。
https://pnpm.io/npmrc#manage-package-manager-versions

この機能が出る前までは volta でバージョンを揃えていましたが、volta だと、(volta を CI に入れない限り)CI のバージョンまでは揃えられないので pnpm のこの機能は大変ありがたいです。

https://docs.volta.sh/advanced/pnpm

pnpm でパッケージをインストール

pnpm には pnpm imoprt というコマンドがあり、これを用いることで移行前のロックファイルから必要なパッケージをインストールすることができます。

pnpm import yarn.lock
pnpm i --frozen-lockfile

追加で必要なパッケージをインストールする

基本は pnpm import で大丈夫なのですが、一部のパッケージが not found になってしまいました。
これは、yarn v1 では直接 package.json に書かれていないパッケージでも、使用しているパッケージが内部で使用していれば import できてしまうからです。つまり今まで暗黙的に import していたパッケージを package.json に明記してインストールする必要があります。

このような暗黙的な import がなければ pnpm import だけでも動作するのですが、残念ながらそうはいかず、いくつか追加でインストールする必要がありました。この作業は面倒ではありますが、今までがむしろ危険な状態で、この機会により安全にパッケージを管理できるようになったということでもあります。

pnpm catalog

この機能のために移行したと言っても過言ではありません。詳しい説明は省略しますが、これを用いると異なる workspace のパッケージ間で共通のバージョンを使用することができます。

例えば、packages/apacakges/b が両方とも react を使っていた場合、今までは両方のpackages.jsonreact のバージョンを書いていました。これらのバージョンは揃えたい場合、バージョンアップのときに両方の package.json を更新する必要があります。catalog 機能を使えばバージョンをトッププレイヤーで宣言して各 package.json はそれを参照する形になるので、明確にバージョンを揃えることができます。

https://zenn.dev/layerx/articles/19691b45fd261d

https://pnpm.io/ja/catalogs

当然、バージョンの共通化には段階的にアップデートできなくなるなどのデメリットもあるので、共通のパッケージをすべて catalog で管理するわけではなく、運用上同一バージョンになっているべきパッケージのみをcatalogで管理するようにしています。

pnpm patch

パッチを当てて管理していたパッケージがあるので、それを pnpm patch で管理するようにしました。今まではpatch-packageを使って管理ししていました。

今までの使用していたパッチファイルを削除して、pnpm patch で新規にパッチを作成するだけで簡単に移行できました。パッチの管理をパッケージマネージャに任せられるようになったのありがたいです。

https://pnpm.io/ja/cli/patch

CI で pnpm のセットアップ

AI Shift では CI に GitHub Actions を使用しています。pnpm 公式が GitHub Actions 用のアクションを用意してくれているのでそれを使えば問題ないと思います。corepack を使う方法もありますが、前述の通り corepack は使用しない方針にしたので CI でも使いません。

pnpm setup action は jobのyamlファイルに pnpm のバージョンを指定するか、package.jsonpackageManager フィールドのどちらかでバージョンを指定できます。ローカルとのバージョンを揃えたいので基本的には packageManger に指定する形で良いかなと思います。

https://github.com/pnpm/action-setup?tab=readme-ov-file#setup-pnpm

まとめ

corepack が Node.js から外されることもあり、pnpm の管理については少し悩みましたが、yarn から pnpm への移行自体はそこまで大変ではありませんでした。移行後はインストールが高速になり、パッケージのバージョンも安全に管理できるようにうになりました。pnpm は今も便利な機能が追加されているので、今後もリリース情報を追ってうまく活用していきたいと思います。

最後に

AI Shiftではエンジニアの採用に力を入れています!
少しでも興味を持っていただけましたら、カジュアル面談でお話しませんか?
(オンライン・19時以降の面談も可能です!)

【面談フォームはこちら】
https://hrmos.co/pages/cyberagent-group/jobs/1826557091831955459

AI Shift Tech Blog

Discussion