【やっと】npmからpnpmへ移行【Homebrew & nodebrew環境での導入方法】


## はじめに

JavaScriptプロジェクトの開発において、パッケージマネージャーは欠かせないツールです。
長らく`npm`がデファクトスタンダードとして使われてきましたが、近年は`pnpm`のような代替ツールが注目を集めています。

本記事では、`npm`から`pnpm`への移行を検討している開発者、特に`nodebrew`でNode.jsのバージョン管理をしている方に向けて、移行のメリットと具体的な設定手順を解説します。

## 前提条件

- macOS環境（Homebrewがインストール済み）
- nodebrewでNode.js v16.13.0以上が動作していること
- npmの基本的な使い方を理解していること

## 本題

### pnpmとは何か？その特徴と利点

pnpmは高速でディスク効率の良いパッケージマネージャーです。
従来のnpmやyarnと比較して、以下のような特徴があります。

#### 🔥 pnpmが優れているポイント

| 比較項目            | pnpm                                  | npm                                |
|---------------------|---------------------------------------|-------------------------------------|
| インストール速度     | ✅ 速い（ハードリンク使用）            | 遅め                                |
| ディスク使用量       | ✅ 少ない（依存を共有）                | 多い（プロジェクトごとに重複）      |
| 依存の厳格性         | ✅ 厳格（バグの早期発見につながる）     | 緩い                                |
| キャッシュ管理       | ✅ 賢い                                | 普通                                |
| 互換性               | 一部ツールで注意が必要                | ✅ 最も広くサポートされている        |

pnpmの最大の特徴は同じバージョンのパッケージを複数のプロジェクトで共有するという点です。

1. **ディスク容量の大幅な節約**：同じパッケージが重複してインストールされません
2. **インストール速度の向上**：キャッシュとハードリンクを活用した高速なインストール
3. **厳格な依存関係管理**：隠れた依存関係を防ぎ、バグを早期に発見

#### 👎 pnpmの注意点

完璧なツールはありません。pnpmにも以下のような注意点があります。

- 一部のツールやスクリプトがpnpm非対応の場合がある
- チームで統一して使用する必要がある（混在すると問題が生じる可能性）
- 従来のnpmのワークフローに慣れている場合、少し学習コストがかかる
- Node.js v16.13.0以上が必要

### npmとpnpmの動作比較

#### 依存関係の解決方法の違い

npmとpnpmでは、依存関係の解決方法に大きな違いがあります。

**npmの場合**：
- 各プロジェクトごとに `node_modules` ディレクトリにすべての依存パッケージをフラットにインストール
- ディスク使用量が多くなりがち
- 「ファントム依存関係」問題（明示的に依存関係を宣言していなくても利用できてしまう）が発生

**pnpmの場合**：
- 依存パッケージはグローバルストアに一度だけインストールされ、プロジェクト間で共有
- `node_modules` 内には実際のファイルではなくシンボリックリンクを配置
- 「ファントム依存関係」問題を回避する厳格な依存関係管理

#### ロックファイルの違い

```
# npmの場合
package-lock.json

# pnpmの場合
pnpm-lock.yaml
```

どちらも依存関係を正確に再現するためのファイルですが、形式と内部構造が異なります。

### セットアップ手順

pnpmのインストールは様々な手順がありますが、Homebrew・nodebrewを利用していればシンプルに導入することができます。

### 🔧 セットアップコマンド

```bash
# 1. Homebrewでpnpmをインストール
brew install pnpm

# 2. インストールの確認
pnpm -v
10.11.0
```


### pnpmの基本的な使い方

npmを使っていた方がpnpmに移行する際の、基本的なコマンドの対応表です。

| 操作                | npm                    | pnpm                   |
|---------------------|------------------------|------------------------|
| インストール         | `npm install`          | `pnpm install`         |
| パッケージの追加     | `npm install パッケージ` | `pnpm add パッケージ`   |
| 開発用パッケージの追加 | `npm install -D パッケージ` | `pnpm add -D パッケージ` |
| グローバルインストール | `npm install -g パッケージ` | `pnpm add -g パッケージ` |
| スクリプト実行       | `npm run スクリプト名`   | `pnpm スクリプト名`     |
| パッケージの削除     | `npm uninstall パッケージ` | `pnpm remove パッケージ` |
| 依存関係の更新       | `npm update`          | `pnpm update`         |
| 依存関係の分析       | `npm ls`              | `pnpm why パッケージ`   |
| キャッシュのクリーン  | `npm cache clean`     | `pnpm store prune`    |
| 不要パッケージの削除  | `npm prune`           | `pnpm prune`          |
| セキュリティ監査     | `npm audit`           | `pnpm audit`          |

特に注目すべき点は、`pnpm`ではスクリプト実行時に`run`を省略できることです。
これにより日常的なコマンド実行がより簡潔になります。

### pnpmへの移行手順（既存プロジェクト）

既存のnpmプロジェクトをpnpmに移行する手順を紹介します。

```bash
# 1. 既存の依存関係をクリーンアップ
rm -rf node_modules package-lock.json

# 2. .npmrcファイルの作成（pnpmの設定）
echo "engine-strict=true" > .npmrc
echo "use-pnpm=true" >> .npmrc

# 3. pnpmでインストールを実行
pnpm install
```

これで、プロジェクトがpnpmを使用するように変更されます。
`pnpm-lock.yaml`が生成され依存関係が再構築されます。

### 高度な機能

pnpmにはより高度な機能も用意されています。

- 🌟**Workspaces機能**: モノレポ管理に便利な機能です。詳しくは[公式ドキュメント](https://pnpm.io/workspaces)をご覧ください。
- **パッチ機能**: 依存パッケージにパッチを適用できる機能です。
- **プラグインシステム**: 機能を拡張できるプラグインシステムを提供しています。

## まとめ

npmからpnpmへの移行は、以下のようなメリットをもたらします：

- ディスク使用量の削減
- インストール速度の向上
- より厳格な依存関係管理
- 豊富な機能と拡張性

最初は新しいコマンドや概念に慣れる必要がありますが、一度使い始めると、その効率性と一貫性から開発体験が向上するでしょう。

## 参考資料

- [pnpm公式ドキュメント](https://pnpm.io/)
- [pnpm vs npm vs Yarn比較記事](https://blog.logrocket.com/javascript-package-managers-compared/)
- [pnpmのWorkspaces機能](https://pnpm.io/workspaces)
- [pnpmのパッチ機能](https://pnpm.io/cli/patch)