TL;DR
npm と同じ役割を持つパッケージマネージャ。依存パッケージを 1 か所のストアにまとめて置き、各プロジェクトからはリンクで参照するので、ディスクを節約でき、インストールも速い。
なぜ必要か
npm は同じ依存パッケージをプロジェクトごとに別々にコピーする。また、npm や Yarn Classic はすべてのパッケージを node_modules の直下に巻き上げるので、コードが宣言していないパッケージを import できてしまう。
仕組み
pnpm は依存パッケージを内容でアドレスを決めるストア(content-addressable store)に置き、プロジェクトからはハードリンクか copy-on-write のクローンで参照する。同じパッケージの別のバージョンでも、中身が同じファイルは共有するので、変わったファイルだけが追加される。
インストールでは、依存関係の解決、取得、書き込みをすべてのパッケージでそろえて進めず、準備のできたパッケージから次の段階に進める。
node_modules の直下には、そのプロジェクトが直接依存するパッケージだけをシンボリックリンクで置き、依存関係のツリー全体は node_modules/.pnpm に置く。
注意点
シンボリックリンクをうまく扱えないツールでは、nodeLinker を hoisted にすると npm と同じような配置にできる。また、モノレポで使うときは pnpm-workspace.yaml を別に作る必要があり、Workspace 内の別のパッケージを依存に含めるには "workspace:*" のような接頭辞を付ける。