pnpmとは|特徴とnpm・yarnとの違い・導入手順を解説
最終更新日:2026/07/22
pnpmとは、同一内容のパッケージをコンテンツアドレス方式の共有ストアで再利用し、各プロジェクトからハードリンクで参照する設計のNode.js向けパッケージマネージャです。ディスク容量を抑えつつインストールを高速化できる仕組みで、npm・yarnとの違いや導入手順、モノレポでの使い所を、フリーランスエンジニアが案件現場で判断できるレベルで整理します。
先に結論
pnpmは、コンテンツアドレスストア+ハードリンクで同じパッケージを1回だけディスクに置く設計のパッケージマネージャ
非フラットなnode_modulesにより、宣言していない依存の"うっかり読み込み"を起こしにくくする
モノレポ/workspaces/catalogsの対応が厚く、大規模リポジトリでの依存共有に強い
高速さは環境やキャッシュ状態で変わるが、ディスク使用量の削減効果は再現性が高い
「hoisted前提」のライブラリでは追加設定が必要になり、案件によっては選定を保留するほうが無難
この記事でわかること
pnpmの設計思想と、npm・yarnとの具体的な違い
導入手順(Corepack/スタンドアロン/npm経由)と主要コマンドの対応
workspacesとcatalogsを使ったモノレポ運用の考え方
フリーランス案件での採用状況の見え方と、選定判断のチェックポイント
目次
pnpmとは|設計思想と3つの特徴
pnpm・npm・yarnの違いを比較表で整理
pnpmを選ぶ判断基準(メリット・デメリット)
pnpmの導入手順
主要コマンドとnpm/yarn対応表
モノレポ・ワークスペースでの使い方
フリーランス案件でのpnpm動向
よくあるトラブルと対策
実践チェックリスト
まとめ
よくある質問
pnpmとは|設計思想と3つの特徴
pnpmは「Performant npm」を語源とする、Node.js用のパッケージマネージャです。npmやyarnと同じpackage.json・node_modulesの世界で動きますが、依存の格納方法と参照方法が根本から違います。
結論として、pnpmを特徴づけているのは次の3点です。
コンテンツアドレスストアとハードリンクによる重複排除
非フラットなnode_modulesによる依存の明示性
依存の解決・取得・リンクを並列化した高速化
コンテンツアドレスストアとハードリンク
pnpmは、ダウンロードしたパッケージをホームディレクトリの共有ストア(既定では~/.local/share/pnpm/storeなど)に1バージョンにつき1回だけ保存します。プロジェクト側のnode_modulesには、そのストアのファイルへのハードリンクが張られます。
同じライブラリを10個のプロジェクトで使っても、ディスク上の実体は1つです。npmやyarnの既定挙動では各プロジェクトのnode_modulesにファイルを複製するため、パッケージが重い(TypeScriptやeslintなど)ほど差が出ます。公式ドキュメントの説明でも、ストアはグローバルな共有領域として設計されている点が明記されています(pnpm Motivation)。
副次的な効果として、アップデート時の差分書き込みが小さくなるメリットもあります。マイナーな変更を含む更新であれば、変更されたファイルだけがストアに追加され、他は再利用されます。
非フラットなnode_modules構造
npmとyarn Classicは、依存関係をnode_modulesルートにフラットに巻き上げる(hoist)のが既定でした。この方式だと、直接依存していないパッケージもrequireやimportできてしまい、暗黙の依存が生まれます。
pnpmは既定で、node_modulesルートには直接依存のみを配置し、間接依存はnode_modules/.pnpm/配下にネストして格納します。ルートにあるパッケージ名はシンボリックリンクで、実体は.pnpm/内のディレクトリを指します。
この仕組みで、「宣言していないのに動いてしまう」問題が減ります。反面、hoistされていることを前提にしたツールやテンプレートでは、期待通りに動かない場合があり、必要に応じてnode-linker=hoistedやpublic-hoist-patternで挙動を寄せる調整が入ります。
並列インストールによる高速化
インストールを「解決」「取得」「リンク」の3段階に分け、それぞれを同時並行で進める設計になっています。ストアからのハードリンクは実体コピーより軽い操作なので、キャッシュが温まった状態では体感差が出やすい部分です。
ただし、「常に一番速い」ではありません。クリーンインストール直後・大量のpost-installがある構成・仮想化やネットワーク越しのファイルシステムなど、環境で結果が変わります。速度目当てで導入する場合は、対象プロジェクトで実測する前提で見ておくのが安全です。
ミニFAQ
Q. pnpmで作ったnode_modulesをZIPで配布しても動きますか?
A. 既定の設定では動きません。node_modules内のシンボリックリンクとハードリンクが前提のため、圧縮・展開でリンク情報が壊れるとCannot find moduleが出ます。CI/CDでキャッシュする場合は、~/.local/share/pnpm/storeとロックファイルをキャッシュ対象にする方が向いています。
pnpm・npm・yarnの違いを比較表で整理
まず1枚の表で全体像を押さえ、後続節で個別に深掘りします。表の内容は各公式ドキュメントの記述に沿ってまとめています(pnpm Feature Comparison、npm Docs、Yarn Docs)。
観点 | pnpm | npm | yarn(Berry / v3以降) |
|---|---|---|---|
依存の格納 | コンテンツアドレスストア+ハードリンク | プロジェクト内に複製 | nodeLinker設定により異なる(node_modules方式 / PnP方式) |
node_modules構造 | 既定で非フラット(isolated) | 既定でhoisted | 選択可能(hoisted / PnP / pnp-loose 等) |
workspaces | 対応 | 対応 | 対応 |
Plug'n'Play | 設定で有効化可能 | 非対応 | 既定で対応 |
Zero-Installs | 非対応 | 非対応 | 対応 |
autoinstall peers | 対応 | 手動対応 | 非対応 |
依存パッチ(patch) | 対応 | 非対応 | 対応 |
catalogs(依存バージョン共有) | 対応 | 非対応 | 非対応 |
依存管理方式の違い
npmはシンプルさが強みで、Node.jsに標準で同梱されているため追加導入なしで使い始めやすい選択肢です。yarn Berry(v2以降)はPlug'n'Playでnode_modules自体をなくし、.pnp.cjs経由で依存を解決する野心的な設計です。pnpmはnode_modulesを維持しつつ依存の実体を共有するという中間路線を取ります。
現場で判断するときの粗い目安は次のとおりです。
依存の暗黙アクセスを潰したい/CIのディスク圧を抑えたい → pnpm
Zero-Installsでgit clone && yarn startに寄せたい → yarn(PnP)
ツールのpost-installや古いライブラリの互換性を最優先したい → npm
workspaces / モノレポ対応
3つともworkspacesに対応していますが、pnpmはcatalogs(複数パッケージ間で依存バージョンを一元管理する機能)に対応しており、モノレポで「Reactのバージョンをリポジトリ全体で揃える」といった運用が組みやすくなっています。yarnはconstraintsで似た統制ができ、npmはoverridesで部分的にカバーする形です。
パッチ・PnP・Zero-Installs対応
patchは、ライブラリのバグを暫定でその場修正する機能で、pnpmとyarnが対応します(pnpm patch パッケージ名)。PnPはyarnが本気度高く、pnpmはオプション扱いです。Zero-Installsはyarn固有で、依存を.yarn/cacheにコミットしてCIのinstallステップを丸ごと省く運用に向きます。
ミニFAQ
Q. pnpmとyarn Berry、どちらが将来性がありますか?
A. 一方が消えて片方が残るという状況にはなっていません。技術選定の観点では、社内標準・案件のCI環境・使う予定のライブラリの互換性で決めるほうが実務的です。「モノレポでReact系フレームワークを大量に扱う」ならpnpm、「Zero-Installsで環境差を減らしたい」ならyarn、と役割で見るのが無難です。
pnpmを選ぶ判断基準(メリット・デメリット)
結論として、pnpmは中〜大規模/依存が多い/モノレポのプロジェクトほど恩恵が出ます。逆に、単一の小さなCLIツールやレガシー構成では、切り替えコストと合わなくなるケースもあります。
pnpmが向いているケース
Reactアプリを複数抱えるモノレポで、依存バージョンを揃えたい
CIのディスク容量が制約になっており、キャッシュ効率を上げたい
eslintやTypeScriptなど重い依存を複数プロジェクトで使い回している
「宣言していないパッケージを暗黙参照する」バグを予防したい
turborepoやNxなどのモノレポツールと組み合わせる予定がある
注意点・ハマりどころ
postinstallスクリプトが厳格化されており、明示的な許可(onlyBuiltDependencies)が必要な場合がある
hoisted前提のツール(一部のReact NativeやElectron関連)で追加設定が必要
Windowsのユーザー環境で、シンボリックリンクの権限まわりに気を配る必要がある
既存プロジェクトから移行する際、package-lock.jsonとpnpm-lock.yamlの共存は避けるべきで、通常はどちらか一方に統一する運用になる
ミニFAQ
Q. 途中でnpmとpnpmを混在させたらどうなりますか?
A. node_modulesとロックファイルの不整合が起きやすくなります。CIで片方、ローカルでもう片方といった状態は、peer dependency警告や再現不可能なバグの温床です。切り替えを決めたら、リポジトリ単位で片方のロックファイルとコマンドに統一するのが基本です。
pnpmの導入手順
pnpmはNode.jsに同梱されていないため、別途インストールが必要です。必要なNode.jsのバージョンはpnpmのメジャーバージョンごとに変わるため、導入前に公式のInstallationページで対応バージョンを確認してください(pnpm Installation)。本記事執筆時点ではpnpm v10系が公式リリースの主軸ですが、バージョン番号は公式リリースノートで最新を確認するのが安全です。
主な導入経路は3つです。
Corepack経由(推奨)
Node.js 16.10以降に同梱されている公式のパッケージマネージャ切り替えツール、Corepackを使う方法です。プロジェクトのpackage.jsonのpackageManagerフィールドで明示したバージョンが自動的に使われるため、チーム間でバージョンが揃います。
導入は「corepack enable pnpm」を実行してCorepackを有効化し、続けて「corepack use pnpm@latest」で使うバージョンをリポジトリに書き込みます。実行後、package.jsonにpackageManager: pnpm@x.y.z+sha512.xxxxxのような1行が自動追加されます。環境によってはCorepackの有効化や更新が必要になるため、実行前に「corepack --version」で状態を確認し、必要に応じて公式ドキュメントの手順に従ってアップデートしてください。
Corepackを推奨する理由は「バージョンをリポジトリで固定できる」点にあります。個人のグローバル環境に依存しないため、pnpm-lock.yamlと組み合わせると再現性が上がります。
スタンドアロンスクリプト
Node.jsがない環境でも導入できる方法です。macOS(Apple Silicon)とLinux、WindowsのPowerShellでインストールコマンドが用意されています。
「curl -fsSL https://get.pnpm.io/install.sh | sh -」のようなワンライナーで導入するタイプで、CIコンテナのブートストラップに向きます。対応プラットフォームは変更される可能性があるため、スタンドアロン導入の前に公式Installationページで対象OS・CPUの掲載状況を確認してください。
npmグローバルインストール
Node.jsが既にある環境なら、npm install -g pnpmでも入ります。既存の資産と衝突しないため、まず試すだけならこの経路が最短です。ただし、バージョン固定のしやすさではCorepackに劣るため、本格運用に入るタイミングでCorepackへ移すのが定石です。
主要コマンドとnpm/yarn対応表
コマンド名がほぼ揃っているのがpnpmの学習コストの低さです。既存のnpm/yarnユーザーは、以下の対応表を見れば当日から作業に入れます。
目的 | pnpm | npm | yarn |
|---|---|---|---|
依存インストール | pnpm install | npm install | yarn install |
パッケージ追加 | pnpm add パッケージ名 | npm install パッケージ名 | yarn add パッケージ名 |
dev依存で追加 | pnpm add -D パッケージ名 | npm install -D パッケージ名 | yarn add -D パッケージ名 |
パッケージ削除 | pnpm remove パッケージ名 | npm uninstall パッケージ名 | yarn remove パッケージ名 |
スクリプト実行 | pnpm スクリプト名 | npm run スクリプト名 | yarn スクリプト名 |
一時実行 | pnpm dlx コマンド | npx コマンド | yarn dlx コマンド |
依存の更新 | pnpm update | npm update | yarn up |
実行環境の確認 | pnpm doctor | npm doctor | 個別コマンド |
install / add / remove
pnpmではpnpm iがpnpm installのショートハンドで、pnpm addはpackage.jsonへの書き込みを伴う追加操作です。npmは両方がnpm installにまとめられているため、意図がコマンドで明確になる点はpnpmの読みやすさに寄与します。
run / exec / dlx
pnpm run スクリプト名だけでなく、pnpm スクリプト名と直接書けます。pnpm exec 実行ファイル名はプロジェクトのnode_modules/.binのバイナリを実行、pnpm dlx パッケージ名は一時ダウンロードして実行するnpx相当です。dlx系はnode_modulesを汚さないため、create-next-appのようなスキャフォールドで使うと後始末が楽になります。
モノレポ・ワークスペースでの使い方
pnpmはworkspacesとcatalogsの組み合わせで、モノレポ運用が組みやすくなっています。リポジトリ直下にpnpm-workspace.yamlを置き、対象ディレクトリの列挙とcatalogセクション(例:reactやtypescriptのバージョン宣言)を書くのが最小構成です。
workspaces定義
pnpm-workspace.yamlで対象ディレクトリを列挙します(apps配下・packages配下などをワイルドカードで指定するのが一般的)。ルートにnode_modulesを1つだけ持ち、各パッケージからは共有ストアへリンクされる構造になります。「pnpm --filter パッケージ名 スクリプト名」で、対象パッケージだけコマンドを実行できます。
catalogsによる依存共有
catalogセクションでバージョンを宣言し、各パッケージのpackage.jsonからreact: catalog:のように参照します。リポジトリ全体でバージョンを一気に上げられるのがこの機能の実務メリットで、Reactの新メジャーが出た時などに恩恵が大きいポイントです。
フリーランス案件でのpnpm動向
結論として、主要フリーランスエージェント数社の公開案件(週2〜5日・業務委託)を確認した範囲では、「pnpm必須」と明記する案件はnpm・yarn指定に比べて件数が少なく、パッケージマネージャの指定自体がない案件も多い状況です。React/Next.js/TypeScriptの中〜大規模モノレポ案件で採用例が見られやすい傾向があり、Turborepo・Nxを併用する案件との親和性が高いポジションです。
JavaScript/TypeScript案件での採用状況
主要フリーランスエージェントの公開案件(週2〜5日・業務委託)を見る限り、フロントエンド/フルスタック案件の一部でpnpm-lock.yaml前提の環境が指定されています。単独で高単価に直結する条件になるより、モノレポ運用スキルとセットで評価されるケースが目立ちます。関連する周辺スキル(Turborepo、Nx、Docker、GitHub Actions)を合わせて棚卸しすると受注幅が広がりやすい領域です。
自分が今の実務スキルでどのくらいの単価を狙えるか気になる方は、無料のフリーランスエンジニア単価診断で市場単価の目安を確認できます。単価を体系的に上げる考え方は「フリーランスエンジニアの単価相場と単価の上げ方」でも整理しています。
学習コストと市場価値
コマンド体系がnpmに近く、package.jsonの書き方も互換のため、npm経験者であれば基本コマンドの置き換え自体は短時間で慣れやすい部類です。ハマりどころ(peer依存の警告、postinstall制限、hoisted前提のライブラリ)を一通り経験すると実戦投入できる感触になります。市場価値の観点では、pnpm単体より「モノレポ経験」「ビルドパイプライン設計」の文脈で評価される傾向があります。JavaScript全体の位置づけは「JavaScriptとは?できることや年収、将来性について解説」、TypeScriptとの関係は「TypeScriptとは?JavaScriptとの違いや年収、将来性について解説」に整理しています。
よくあるトラブルと対策
導入時・移行時に踏みやすい落とし穴を、対処方針とセットで整理します。
peer依存の警告
pnpmはpeerDependenciesのバージョン整合を厳しくチェックします。「unmet peer dependency」と出た場合、まずは「pnpm why パッケージ名」で経路を追い、package.json側で明示的にバージョンを揃えるのが基本方針です。必要に応じて.pnpmrcのauto-install-peersを確認・設定し、自動インストールを利用する選択もあります。既定値はバージョンで変わり得るため、公式ドキュメントで確認してください。
postinstall / build script制限
pnpmの新しいメジャーバージョンでは、postinstallなどbuild系スクリプトの扱いが厳格化されており、実行を許可するパッケージを明示的に列挙する運用が推奨されます。package.jsonのpnpm.onlyBuiltDependenciesに対象パッケージ名を書くのが基本方針です。セキュリティ寄りの既定挙動なので、CIで「build script blocked」と出た時は焦らず対象を追加します。既定値・許可方法はバージョンで変わり得るため、利用中バージョンの公式ドキュメントで確認してください。
hoist前提のライブラリでの問題
古めのライブラリや一部のReact Native系ツールは、フラットなnode_modulesを前提にしていることがあります。この場合、.npmrcにnode-linker=hoistedまたはpublic-hoist-pattern[]=*を追加して調整します。ただし、hoistedに寄せるとpnpmの利点である「暗黙依存の防止」は薄れるため、必要最小限に留めるのが定石です。
実践チェックリスト
導入判断の前に、次の観点で1つずつ確認しておくと事故が減ります。
対象プロジェクトのNode.js要件がv22以上に揃っているか
CIのnode_modulesキャッシュ設定を、pnpmストアに切り替えられるか
使っているライブラリにpostinstallが必要なものがあり、onlyBuiltDependenciesの整備が必要か
モノレポ化の予定があるか(なければcatalogsの恩恵は小さい)
チーム内のIntel Mac比率(スタンドアロンスクリプトが使えない環境の有無)
まとめ
pnpmは、コンテンツアドレスストア+非フラットnode_modulesという設計で、依存の重複を減らしながら宣言外の依存を防ぐパッケージマネージャです。速度は環境依存でぶれますが、ディスク使用量とモノレポ運用の楽さは再現性のある利点です。
要点を短く整理します。
移行の初手はCorepack経由。packageManagerフィールドでバージョンを固定する
モノレポやReact系の中規模以上で恩恵が大きい。単一小規模プロジェクトでは無理に移行しない
hoisted前提のライブラリではnode-linker=hoistedやpublic-hoist-patternで調整する
主要コマンドはnpm/yarnと対応しており、切り替えコストは低い
案件では単独スキルより、モノレポ・CIパイプラインとセットで評価される
結論として、依存が多い中〜大規模案件やモノレポでは有力な候補、互換性優先の小規模案件ではnpm継続も合理的な選択です。次のアクションとして、テストプロジェクトを1つ選び「corepack use pnpm@latest」から試すのが最短です。ロックファイルをpnpm-lock.yamlに切り替え、CIで「pnpm install」が通れば、あとは主要コマンドの置き換えだけで日常運用に入れます。
参考リンク
よくある質問
Q1. pnpmは無料で使えますか?
はい、MITライセンスのオープンソースで、商用利用も可能です(pnpm GitHub)。有料のサポート契約が必須というわけでもありません。ただしライセンス上の可否と、社内のセキュリティ・運用ポリシー上の採用可否は別問題です。業務利用の可否は各社の技術選定基準に沿って判断してください。
Q2. Nodeのバージョン管理ツール(nvm・volta等)と共存できますか?
できます。ただし、Corepackを使う場合はNode.js側のバージョンとCorepackが有効になっているかを1回確認してください。voltaを使っているチームでは、voltaにpnpmを管理させる派とCorepackに任せる派で分かれます。リポジトリ内で1つに統一するのが混乱を減らすコツです。
Q3. Denoやbunと比べてどう選ぶべきですか?
Q4. GitHub Actionsで使う時のキャッシュはどう設定すればいいですか?
actions/setup-nodeのcache: 'pnpm'オプションでロックファイル基準のキャッシュが取れます。加えて、pnpm store pathの出力パス(例:~/.local/share/pnpm/store)をactions/cacheでキャッシュすると、より効きます。ジョブ間で共有ストアを使い回せると、依存が多いリポジトリほど短縮効果が出ます。
Q5. pnpm-lock.yamlはコミットすべきですか?
はい、コミットしてください。npmのpackage-lock.jsonと同様、再現可能なビルドの前提になります。ライブラリを配布するnpmパッケージを開発している場合でも、.gitignoreせず入れるのが標準です。
Q6. 会社のnode_modulesポリシーで「hoistedであること」が要件になっています。使えますか?
node-linker=hoistedで挙動を寄せられるため、要件は満たせます。ただし、pnpmの利点である「暗黙依存の防止」は弱まるため、わざわざ切り替える意味が小さいことも多いです。ポリシーの理由(社内ツールの都合か、hoistedに依存しているライブラリがあるのか)を確認したうえで、npm継続かpnpm切り替えかを判断すると建設的です。
Q7. モノレポでない小さいプロジェクトでもpnpmを選ぶ意味はありますか?
ディスク容量の削減効果は単体プロジェクトでもあります。ただし、運用の複雑さを増やしてまで移行する動機は薄めです。「これから小さく始めるが、将来モノレポ化を想定している」ようなケースでは、初期からpnpmで揃えておくと乗り換えコストがゼロになります。
Q8. pnpm独自の設定ファイルはありますか?
.npmrcをそのまま使う設計です。pnpm固有のオプション(node-linker、auto-install-peers、shamefully-hoistなど)も.npmrcに書きます。加えて、workspacesを使う場合はpnpm-workspace.yaml、依存パッチにはpatches/ディレクトリが増えます。設定ファイルが分散しすぎないのは移行時に助かるポイントです。
Q9. IDEの補完はどれくらい効きますか?
VS CodeやWebStormでは、node_modules直下のパッケージ名からの補完が効きます。非フラット構造でも、TypeScriptのモジュール解決には対応しているため、日常の開発体験でnpm・yarnとの差は感じにくいはずです。稀に、hoist前提のプラグイン(レガシーな一部のtsconfigプリセット等)で解決に失敗する場合があり、その際はpublic-hoist-patternで対象を持ち上げます。
Q10. Reactのフレームワーク(Next.js・Remix等)は問題なく動きますか?
Next.jsをはじめとする主要なNode系フレームワークではpnpmでの利用例が一般的です。ただし、正式サポートの範囲や推奨手順は各公式ドキュメントで確認してください。初期テンプレートがnpm前提の説明になっている場合があり、生成直後に「rm package-lock.json」→「pnpm import」→「pnpm install」の順で切り替えるステップが必要になることがあります。この一手間だけで、あとは「pnpm dev」で通常運用に入れます。

