JavaScript、特にNode.jsにおけるパッケージ管理としてnpmがよく使われています。プロジェクトごとにnode_modulesというフォルダが作成されて、その中で必要なパッケージが管理されます。とても便利な仕組みなのですが、node_modulesが肥大化するという問題がよく知られています。さらにそれがプロジェクトごとに存在すると、ディスク容量もあっという間に食いつぶしてしまいます。

今回はそうした問題を解決してくれるpnpmという新しいパッケージ管理を紹介します。他のパッケージ管理との比較も行ってみます。

pnpmのインストール

pnpm自体のインストールはnpmで行います。これは致し方ないでしょう。

$ npm install -g pnpm

終わったら phpmpnpx コマンドが使えるようになります。 phpmnpm 相当、 pnpxnpx 相当のコマンドになります。

インストール速度の比較

では実際にmonacaライブラリをインストールして速度を比較してみます。まず標準のnpmでインストールした場合です。

$ time npm i monaca -S
npm WARN deprecated request@2.88.2: request has been deprecated, see https://github.com/request/request/issues/3142

> monaca@3.3.3 preinstall /Users/nakatsugawa/Downloads/monaca-test/npm/node_modules/monaca
> node bin/preinstall

Checking for XCode ...
OK

Checking for XCode Command Line Tools ...
OK

Success: Confirmed that the dependent components are installed.
npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN npm@1.0.0 No description
npm WARN npm@1.0.0 No repository field.

+ monaca@3.3.3
added 231 packages from 220 contributors and audited 231 packages in 11.64s

4 packages are looking for funding
  run npm fund for details

found 1 low severity vulnerability
  run npm audit fix to fix them, or npm audit for details

real    0m12.132s
user    0m6.123s
sys 0m2.521s

これは普通のコマンドで、12秒かかっています。では次にpnpmを使ってみます。

$ time pnpm add monaca
Packages: +228
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Packages are hard linked from the content-addressable store to the virtual store.
  Content-addressable store is at: /Users/nakatsugawa/.pnpm-store/v3
  Virtual store is at:             node_modules/.pnpm
Resolving: total 228, reused 228, downloaded 0, done
node_modules/.pnpm/monaca@3.3.3/node_modules/monaca: Running preinstall script..node_modules/.pnpm/monaca@3.3.3/node_modules/monaca: Running preinstall script, done in 74ms

dependencies:
+ monaca 3.3.3

real    0m4.790s
user    0m3.163s
sys 0m5.636s

4.7秒でインストールされています。標準のコマンドに比べて3倍近い速度でインストールが完了しています。

同じようにnpmの代替となるパッケージ管理、yarnでも試してみます。

$ time yarn add monaca
yarn add v1.22.4
info No lockfile found.
[1/4]   Resolving packages...
warning monaca > monaca-lib > request@2.88.2: request has been deprecated, see https://github.com/request/request/issues/3142
[2/4]   Fetching packages...
[3/4]   Linking dependencies...
[4/4]   Building fresh packages...
success Saved lockfile.
success Saved 182 new dependencies.
info Direct dependencies
└─ monaca@3.3.3
info All dependencies
├─ adbkit-logcat@1.1.0
  :
├─ yargs@3.15.0
└─ yauzl@2.10.0
✨  Done in 8.24s.

real    0m8.452s
user    0m5.850s
sys 0m5.081s

この場合、8.4秒です。npmよりは速いですが、pnpmには及びません。

もう一つ、Rustで作られたパッケージ管理であるVoltaを使ってみました。こちらも高速性が売りですが、10秒かかってしまいました。

$ time volta install monaca
success: installed monaca@3.3.3 with executables: monaca

real    0m10.370s
user    0m10.493s
sys 0m3.027s

これらの比較でもpnpmがいかに高速か分かるかと思います。

ファイル管理について

次にファイル管理の状態を紹介します。通常、node_modulesの中にはインストールしたライブラリとその依存ライブラリがフォルダに分かれて並んでいます。

それに対してpnpmの場合は、インストールしたライブラリだけがあり、シンボリックリンク(ハードリンク)が作られています。実際のファイルは .pnpm フォルダの中にあります。

このようにシンボリックリンクを使うことで、実体を重複させることなく管理できるようになっています。requireなどはこれまで通り使えますので問題ありません。

乗り換える際には

pnpmはこれまでのNode.jsプロジェクトと同じくpackage.jsonが使えます(package-lock.jsonは使いません)。乗り換える際には一旦これまでのnode_modulesを削除し、pnpmをインストールした上で pnpm install コマンドを使ってライブラリをインストールし直してください。

まとめ

詳細はドキュメントがありますので、そちらを参照してください。基本的にはこれまでと変わらない使い方で、高速なライブラリインストールとディスク容量削減効果が望めるはずです。

pnpmを使うことで、ライブラリインストール時に時間がかかって待たされることもなくなるでしょう。開発をさくさくと進める上でも、高速なパッケージ管理は導入する価値がありそうです。

pnpm · Fast, disk space efficient package manager