
npmやYarnからの移行を検討していると、必ず選択肢に上がるpnpm とBun 。どちらも「npmより速い」とアピールしていますが、実際のところ何が違うのでしょうか。
State of JS 2024では、pnpmは「継続利用意向(retention)」が高く、開発者からの評価が安定していることがわかります。一方で、Bunも新しい選択肢として存在感を増しています。しかし、両者の設計思想は対照的です。pnpmは「正しい依存関係管理」を、Bunは「速度とDX」を追求しています。本記事では、この2つのパッケージマネージャの違いを整理し、あなたのプロジェクトに合った選択肢を見つけるヒントを提供します。
npmの何が問題だったのか
移行を考える前に、まずnpmの抱える課題を整理しましょう。
1. 遅いインストール速度
公式ベンチマーク(2026年1月時点)によると、clean installの速度は以下の通りです:
| パッケージマネージャ | 時間 |
|---|---|
| npm | 34.1秒 |
| pnpm | 8.5秒(4倍速) |
| Yarn Classic | 7.2秒 |
| Yarn PnP | 3.5秒 |
ローカル開発での npm install 待ち時間だけでなく、CI/CDパイプラインでの累積時間を考えると、この差は無視できません。
2. ディスクスペースの浪費
npmはプロジェクトごとに node_modules にパッケージをコピーするため、同じパッケージが複数プロジェクトで重複します。10個のプロジェクトで同じ依存関係を持つと、10倍のディスク容量を消費します。
3. 隠れた依存関係(Phantom Dependencies)
npmのフラットな node_modules 構造では、package.json に明示的に書いていない依存関係でも require() できてしまいます。これにより、実際には依存しているのに package.json に記載されていない「ファントム依存」が生まれ、プロジェクトの移植性を損ないます。
pnpmの哲学:正しさと堅牢性
pnpm(performant npm)は、npmの問題を「正しい方法」で解決しようとするパッケージマネージャです。
Content-Addressable Store
pnpmの最大の特徴は、グローバルな Content-Addressable Store を使用する点です。全てのパッケージは一度だけディスクに保存され、各プロジェクトの node_modules からハードリンクで参照されます。
| |
これにより、プロジェクト数が増えるほどディスク使用量を大きく削減できます。
ストアの場所は環境によって異なるので、pnpm store path で確認できます。
厳格な依存関係管理
pnpmは node_modules 内にシンボリックリンク構造を作成し、package.json に記載された依存関係のみがアクセス可能になります。
| |
この仕組みにより、Phantom Dependencies を技術的に防止します。npmでは動いていたコードがpnpmで壊れる場合、それは潜在的なバグが顕在化しただけです。
移行時に直面する現実
pnpmへの移行で最も多い問題は、まさにこの「正しさ」です。以下のようなコードが動かなくなります:
| |
修正方法は明確です:
| |
この「壊れる」体験は、プロジェクトの健全性を診断する良い機会です。Redditのスレッド では、「4日かかったが100%価値があった」という報告もあります。
Bunの哲学:速度とDX
Bunは、パッケージマネージャの枠を超えた「オールインワンJavaScriptランタイム」です。
Zigで書かれた高速性
BunはZig言語で実装されており、パッケージマネージャだけでなく、JavaScriptランタイム、テストランナー、バンドラーを統合しています。
| |
全てが統合されているため、ツールチェーンの切り替えコストがなく、一貫したDX(開発者体験)を提供します。
速度重視のアーキテクチャ
Bunのインストール速度は驚異的です。公式ベンチマークでは、pnpmやYarnをさらに上回る速度を記録しています。ただし、これは従来のContent-Addressable Storeとは異なるアプローチによるものです。
互換性の課題
Bunの最大の課題はNode.jsエコシステムとの互換性です。ネイティブモジュール(.node ファイル)や一部のAPIで問題が発生することがあります。
| |
公式は「100%互換を目指す」旨を掲げていますが、実際のプロジェクトでは一部の差分が致命的になる場合があります。
どちらを選ぶべきか:プロジェクト特性別ガイド
pnpmを選ぶべきケース
以下の条件に当てはまる場合、pnpmが最適です:
- 大規模プロジェクト/モノレポ: 複数パッケージの依存関係を厳格に管理したい
- CI/CDコストが気になる: GitHub Actions等の課金を削減したい
- 長期運用: 依存関係の健全性を重視する
- npmからの移行: 互換性が高く、段階的に移行できる
特にTurborepo やNx を使ったモノレポ構成では、pnpm workspaceが定番になっています。
| |
Bunを選ぶべきケース
以下の条件に当てはまる場合、Bunが最適です:
- 新規プロジェクト: グリーンフィールドで互換性問題が少ない
- 速度至上主義: 開発サイクルの高速化を最優先
- TypeScriptメイン: ネイティブモジュールへの依存が少ない
- 実験的プロジェクト: 最新技術にキャッチアップしたい
特に個人プロジェクトやスタートアップの初期段階では、Bunの統合性とスピードが開発効率を大きく向上させます。
両方試す価値がある理由
実は、pnpmとBunは排他的ではありません。以下のような使い分けも可能です:
| |
移行の実際:4つのステップ
1. 準備(npm → pnpm/Bun)
| |
2. 互換性確認
| |
3. Phantom Dependencies の修正(pnpmの場合)
エラーが出たパッケージは明示的に追加します:
| |
4. CI/CDの更新
| |
まとめ:思想の違いが選択を決める
pnpmとBun、どちらも「npmより速い」という点では共通していますが、その根底にある思想は大きく異なります。
pnpm は、正しさと堅牢性を追求します。Phantom Dependenciesを防ぎ、ディスク効率を高め、長期的なプロジェクトの健全性を保証します。移行時に「壊れる」のは、むしろプロジェクトの隠れた問題を発見するチャンスです。
Bun は、速度とDXを追求します。パッケージマネージャ、ランタイム、テストランナー、バンドラーを統合し、一貫した高速体験を提供します。新規プロジェクトや実験的な開発で真価を発揮します。
どちらを選ぶかは、あなたのプロジェクトの優先順位次第です。大規模で長期運用ならpnpm、速度と革新性を求めるならBun。幸い、両者とも移行コストは低く、気軽に試せます。
npmの node_modules 地獄に疲れたなら、まずは小さなプロジェクトでどちらかを試してみてください。その体験が、あなたの次のプロジェクトでの選択を決めるはずです。