pnpm
パッケージマネージャー
pnpm
概要
pnpm(performant npm)は、npmとYarnの代替として開発された高速でディスク効率の良いJavaScript/TypeScriptパッケージマネージャーです。ハードリンクとシンボリックリンクを活用してパッケージを1つのグローバルストアに保存し、プロジェクト間でディスク容量を共有することで、従来の3倍高速で最大50%のディスク容量を節約できます。npm/Yarnとの完全な互換性を保ちながら、厳密な依存関係管理、効率的なモノレポサポート、セキュリティの向上を実現した次世代パッケージマネージャーです。
詳細
pnpmは2017年にZoltan Kochanによって開発され、既存のパッケージマネージャーの問題を解決するために設計されました。最大の特徴は、Content-Addressable Store(CAS)というアプローチで、すべてのパッケージバージョンをグローバルストアに一度だけ保存し、プロジェクト間でハードリンクによって共有することです。これにより、同じパッケージを複数のプロジェクトで使用してもディスク上には1つのコピーしか存在しません。また、node_modules/.pnpmディレクトリにフラット構造でパッケージを配置し、シンボリックリンクで適切な依存関係ツリーを構築します。これにより、phantom dependencies(幻の依存関係)やnpm doppelgängers問題を解決し、より安全で一貫性のある依存関係管理を実現しています。
メリット・デメリット
メリット
- ディスク効率: ハードリンクによる容量節約(最大50%削減)
- 高速インストール: 既存パッケージの再利用により3倍高速
- 厳密な依存関係: phantom dependenciesを防ぐ安全な構造
- モノレポサポート: 効率的なワークスペース機能
- npm互換性: 既存のnpmプロジェクトで即座に使用可能
- セキュリティ: パッケージの分離とアクセス制御の向上
デメリット
- シンボリックリンク: 一部のツールがシンボリックリンクに対応していない場合がある
- Windows制限: 古いWindowsバージョンでのハードリンク制限
- 学習コスト: .pnpmディレクトリ構造の理解が必要
- デバッグ複雑さ: 複雑なリンク構造によるデバッグの困難さ
参考ページ
書き方の例
基本的なパッケージ管理
# pnpmのインストール
npm install -g pnpm
# または
curl -fsSL https://get.pnpm.io/install.sh | sh -
# プロジェクトの初期化
pnpm init
# パッケージのインストール
pnpm install
# パッケージの追加
pnpm add react react-dom
pnpm add -D typescript @types/react
pnpm add -g nodemon
# パッケージの削除
pnpm remove lodash
pnpm remove -D webpack
ワークスペース(モノレポ)設定
# pnpm-workspace.yaml
packages:
- 'packages/*'
- 'apps/*'
- '!**/test/**'
// ルートのpackage.json
{
"name": "my-monorepo",
"private": true,
"scripts": {
"build": "pnpm -r run build",
"test": "pnpm -r run test"
}
}
# ワークスペース全体でのコマンド実行
pnpm -r run build
pnpm -r run test
# 特定のワークスペースでの実行
pnpm --filter @myorg/app run dev
pnpm --filter "./packages/utils" run build
# 依存関係が変更されたパッケージのみ実行
pnpm --filter "...[HEAD~1]" run test
# ワークスペース間の依存関係追加
pnpm --filter @myorg/app add @myorg/utils@workspace:*
高度なフィルタリングとタスク管理
# パターンベースフィルタリング
pnpm --filter "*app*" run build
pnpm --filter "@myorg/*" run lint
# 依存関係ベースフィルタリング
pnpm --filter ...@myorg/core run build # coreに依存するすべて
pnpm --filter @myorg/core^... run test # coreが依存するすべて
# 並列実行制御
pnpm -r --parallel run dev
pnpm -r run build --workspace-concurrency=2
# 特定の条件でのスキップ
pnpm --filter "!@myorg/legacy" -r run test
パッケージ情報とストア管理
# パッケージ情報の表示
pnpm list
pnpm list --depth=0
pnpm list --global
# 依存関係の理由確認
pnpm why lodash
pnpm audit
# ストア管理
pnpm store status
pnpm store prune # 使用されていないパッケージを削除
pnpm store path # ストアパスの表示
.npmrc設定とカスタマイズ
# .npmrc
# ストア場所の指定
store-dir=~/.pnpm-store
# ハードリンクを無効化(必要な場合)
package-import-method=copy
# ワークスペース設定
link-workspace-packages=true
prefer-workspace-packages=true
# ログレベル設定
loglevel=warn
# 自動インストール有効化
auto-install-peers=true
# 依存関係解決の厳密化
strict-peer-dependencies=true
CI/CD環境での最適化
# CI環境での高速インストール
pnpm install --frozen-lockfile
pnpm install --prefer-offline
# キャッシュ活用
pnpm install --ignore-scripts
pnpm rebuild
# プロダクションビルド
pnpm install --prod --frozen-lockfile
pnpm prune --prod
# Docker環境
# package.jsonとpnpm-lock.yamlのみコピーしてインストール
COPY package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile
高度な機能とトラブルシューティング
# パッチ管理
pnpm patch [email protected]
# パッチファイル編集後
pnpm patch-commit /tmp/patch-dir
# リンク管理
pnpm link --global
pnpm link ../local-package
# 重複排除と最適化
pnpm dedupe
pnpm install --fix-lockfile
# 環境変数とスクリプト
PNPM_HOME=/custom/path pnpm install
pnpm exec -- jest --coverage
pnpm dlx create-react-app my-app # npx相当