Open32

[キャッチアップ] pnpm

shingo.sasakishingo.sasaki

スクラップの目的

yarn v1 を使用しているプロジェクトを pnpm に移行したい。

関連する他のプロジェクトではすでに pnpm が概ね普及しているため、シナジーを得るためにも pnpm を採用する。

あわせて corepack も使用するようにしたい。

公式ドキュメントがそんなに大きくないので全部読むところからスタート。

shingo.sasakishingo.sasaki

pnpm のメリット

https://pnpm.io/ja/motivation

  • 複数のプロジェクトで同じ依存パッケージを保つ場合に、それぞれのディレクトリにコピーされるのでなく、共通の探索可能なストアに保持されるため、ディスク容量の節約とインストール速度の向上が期待できる
  • フラットでない node_modules ディレクトリによって、依存パッケージが依存する別のパッケージに対して直接アクセスできてしまうような問題を解消できる
shingo.sasakishingo.sasaki

リポジトリが大量にある組織で、かつ pnpm を採用しているリポジトリが多いほどに効果的っぽい。

shingo.sasakishingo.sasaki

依存パッケージが依存する別のパッケージに対して直接アクセスできてしまう

これほんとよくある。必要なパッケージを依存に追加していないはずなのに何故か動くって問題起こりがち。

shingo.sasakishingo.sasaki

機能の比較

https://pnpm.io/ja/feature-comparison

気になったこと

  • yarn しか使ってなかったから、 peerDependencies の自動インストールなんて機能が pnpm / npm にあるなんて想像もしてなかった
  • Zero-Installs ってなにかと思ったけど、依存パッケージごとコミットしたろうというパワフルな機能らしい
  • Node のバージョン管理も pnpm なら出来ちまうってマジ〜?
shingo.sasakishingo.sasaki

スクリプト

https://pnpm.io/ja/scripts

ライフサイクルスクリプト、devPreinstall しかないの…?そんな事ないと思うけど、なんかこの辺ドキュメント雑じゃない?

shingo.sasakishingo.sasaki

CLI コマンド2

ローカルパッケージを他のプロジェクトから参照できるようにするやつ。あんまりパッケージ開発の経験ないけど、テストするのに使うんだろうな。

  • link
  • unlink

https://pnpm.io/ja/cli/link
https://pnpm.io/ja/cli/unlink

shingo.sasakishingo.sasaki

CLI コマンド 4

rebuild も yarn にあるんだ。といっても v1 にはないみたい。
node_modules 全消ししてからの再インストールとかよくやってたけど、それの代替になるのかな。

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

shingo.sasakishingo.sasaki

CLI コマンド 5

prune ってわざわざ明示的にやらなきゃならんのかな。
https://pnpm.io/ja/cli/prune

yarn だと install 時に同様のことやってくれるから不要らしい。
error The prune command isn't necessary. yarn install will prune extraneous packages.

shingo.sasakishingo.sasaki

CLI コマンド 8

audit で脆弱性検知。outdated で更新情報確認。これは renovate や dependabot でよしなに。
https://pnpm.io/ja/cli/audit
https://pnpm.io/ja/cli/outdated

list たまに便利だけど全ツリーを眺めるよりは why のほう使う気がする。

https://pnpm.io/ja/cli/list
https://pnpm.io/ja/cli/why

licenses あんま眺めたこと無いなぁ。やっちゃいけないことしてしまってる可能性まぁあるな…。
https://pnpm.io/ja/cli/licenses

shingo.sasakishingo.sasaki

CLI はこんなところかな。他にもコマンドいっぱいあるけど、アプリケーション開発では使う場面限られそうなのでよし。

shingo.sasakishingo.sasaki

package.json

package.json 上に記述できる設定。めちゃくちゃたくさんあるのでリファレンス用途で覚えておく。

https://pnpm.io/ja/package_json

とはいえ基本的には npm/yarn 互換だし、パッケージ公開用の設定が殆どな気がする。
あと依存パッケージを強引に書き換えるとかそういうハック用途。

shingo.sasakishingo.sasaki

import コマンドで yarn.lock から乗り換えられるらしい。

$ pnpm import                                  
 WARN  2 deprecated subdependencies found: core-js-pure@3.17.3, stable@0.1.8
Progress: resolved 393, reused 377, downloaded 4, added 0, done

すんなりイケたんかな。

yarn.lock 消して再インストールしてみよ。

$ rm yarn.lock 
$ rm -rf node_modules 
$ pnpm install
Lockfile is up to date, resolution step is skipped
Packages: +381
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Progress: resolved 381, reused 381, downloaded 0, added 381, done
node_modules/.pnpm/@fortawesome+fontawesome-common-types@6.2.0/node_modules/@fortawesome/fontawesome-common-types: Running postinstall script, done in 52ms
node_modules/.pnpm/core-js-pure@3.17.3/node_modules/core-js-pure: Running postinstall script, done in 62ms
node_modules/.pnpm/@fortawesome+fontawesome-svg-core@6.2.0/node_modules/@fortawesome/fontawesome-svg-core: Running postinstall script, done in 50ms
node_modules/.pnpm/@fortawesome+free-solid-svg-icons@6.2.0/node_modules/@fortawesome/free-solid-svg-icons: Running postinstall script, done in 57ms

dependencies:
+ @fortawesome/fontawesome-svg-core 6.2.0
+ @fortawesome/free-solid-svg-icons 6.2.0
+ @fortawesome/react-fontawesome 0.2.0
+ next 12.2.5
+ react 18.2.0
+ react-dom 18.2.0
+ rss-parser 3.12.0

devDependencies:
+ @playwright/test 1.40.1
+ @types/node 20.11.30
+ @types/react 18.0.18
+ autoprefixer 10.4.16
+ babel-plugin-inline-react-svg 2.0.1
+ eslint 8.23.0
+ eslint-config-next 12.2.5
+ postcss 8.4.33
+ prettier 3.2.4
+ prettier-plugin-tailwindcss 0.5.11
+ tailwindcss 3.4.1
+ typescript 4.8.2

Done in 4s

全部 reused になってる。
import した時点でインストールされてて、ストアから node_modules に対してリンク貼っただけってことかな。

shingo.sasakishingo.sasaki

開発環境とE2Eテストどっちも通る。もう移行終わったのか…?

$ pnpm dev
$ pnpm e2e
shingo.sasakishingo.sasaki

package.json 上でバージョンを定義する。

package.json
  "engines": {
    "node": "20.11.1",
    "pnpm": ">=8"
  },
shingo.sasakishingo.sasaki

vercel 側の設定もちょっと弄ってデプロイを確認。
もう終わっちゃった。

shingo.sasakishingo.sasaki

CI 設定とか renovate とかもっと作り込んでるプロジェクトだともう少し手間がかかる気がするので次はそれをやる。