Wer regelmäßig JavaScript-Projekte entwickelt, kennt das Problem: node_modules-Ordner fressen Festplattenplatz, npm install dauert länger als erwartet, und in Monorepo-Setups werden dieselben Pakete immer wieder dupliziert. pnpm – der performante Paketmanager – löst genau diese Probleme durch eine fundamentale Neugestaltung der Art, wie Abhängigkeiten gespeichert werden. Seit Jahren gewinnt pnpm in der JavaScript-Community an Beliebtheit und ist heute die erste Wahl vieler erfahrener Entwickler und großer Projekte wie Vue.js.
Was ist pnpm?
pnpm steht für „performant npm" und ist ein Drop-in-Ersatz für npm und yarn, der jedoch unter der Haube vollständig anders funktioniert. Erstellt von Zoltan Kochan und heute ein aktiv gepflegtes Open-Source-Projekt, verwendet pnpm ein content-addressierbares Dateisystem als zentralen Store – einen einzigen globalen Paket-Cache auf dem System, aus dem alle Projekte ihre Abhängigkeiten beziehen.
Der entscheidende Unterschied zu npm und Yarn liegt in der Art, wie pnpm Pakete in das Projekt einbindet: Es erstellt keine Kopien, sondern Hard-Links vom globalen Store in das projektspezifische node_modules-Verzeichnis. Jedes Paket in einer bestimmten Version belegt Speicherplatz auf der Festplatte daher nur ein einziges Mal – egal wie viele Projekte es verwenden.
Content-Addressable Storage: Das Herzstück von pnpm
Der globale pnpm-Store liegt standardmäßig unter ~/.local/share/pnpm/store auf Linux/macOS oder %LOCALAPPDATA%\pnpm\store auf Windows. Wenn ein Paket installiert wird, prüft pnpm zunächst, ob es bereits im Store vorhanden ist. Falls ja, wird nur ein Hard-Link erstellt – ein Vorgang, der in Nanosekunden abläuft, da keine Daten kopiert werden müssen.
Zudem legt pnpm eine strikt strukturierte node_modules-Architektur an, die „phantomhafte Abhängigkeiten" verhindert. Bei npm und Yarn werden Pakete oft durch einen Hoisting-Prozess in das Root-node_modules hochgezogen, sodass Code theoretisch auf Pakete zugreifen kann, die er gar nicht selbst als Abhängigkeit deklariert hat. pnpm verhindert dies konsequent.
pnpm store prune lässt sich der globale Cache von ungenutzten Paketen bereinigen. Mit pnpm store status kann der aktuelle Stand des Stores überprüft werden. Für eine vollständige Übersicht über den Store-Speicherverbrauch nutzt man pnpm store path und schaut dann in das entsprechende Verzeichnis.
Workspace-Unterstützung für Monorepos
pnpm hat erstklassige Unterstützung für Workspaces – also Monorepos mit mehreren Paketen. Die Workspace-Konfiguration erfolgt über eine pnpm-workspace.yaml im Projektwurzel:
packages:
- 'apps/*'
- 'packages/*'
Damit kann pnpm alle Pakete als Workspace-Members erkennen und interne Abhängigkeiten per workspace:-Protokoll auflösen:
{
"dependencies": {
"@myorg/ui": "workspace:*"
}
}
Befehle können entweder im Root-Kontext oder selektiv für bestimmte Pakete ausgeführt werden:
# Nur in einem bestimmten Paket
pnpm --filter @myorg/ui build
# In allen Paketen
pnpm -r build
# In allen Paketen, die sich seit dem letzten Commit verändert haben
pnpm -r --filter '...[origin/main]' build
.npmrc-Konfiguration
Das Verhalten von pnpm lässt sich über die .npmrc-Datei feintunen. Einige besonders nützliche Optionen:
# Verhindert automatisches Hoisting (empfohlen für saubere Abhängigkeiten)
shamefully-hoist=false
# Erlaubt nur deklarierte Peer-Abhängigkeiten
strict-peer-dependencies=true
# Automatische Installation fehlender Peer-Abhängigkeiten
auto-install-peers=true
# Store-Pfad explizit setzen (z.B. für Netzlaufwerke)
store-dir=~/.pnpm-store
Peer-Abhängigkeiten: Transparenter als npm
Ein häufiges Ärgernis bei npm sind stumm ignorierte oder falsch aufgelöste Peer-Abhängigkeiten. pnpm hat hier eine klarere Haltung: Fehlende Peer-Abhängigkeiten werden standardmäßig als Warnung oder Fehler gemeldet. Mit auto-install-peers=true in der .npmrc kann pnpm fehlende Peers auch automatisch installieren – das ist praktisch für Endprojekte, aber für Bibliotheken sollte es deaktiviert bleiben.
node_modules zugreifen können, die sie nicht explizit als Abhängigkeit deklariert haben. Mit pnpm's strikter Isolation schlägt das fehl. In solchen Fällen hilft shamefully-hoist=true in der .npmrc als temporäre Lösung, aber das eigentliche Problem sollte beim Paketautor gemeldet werden.
Vergleich: pnpm vs. npm vs. Yarn vs. Bun
| Merkmal | pnpm | npm | Yarn Berry | Bun |
|---|---|---|---|---|
| Installationsgeschwindigkeit | Sehr schnell | Mittel | Schnell | Extrem schnell |
| Festplattenverbrauch | Minimal (Hard-Links) | Hoch (Kopien) | Gering (Zero-Installs möglich) | Gering |
| Workspace-Unterstützung | Erstklassig | Basis | Sehr gut | Gut |
| Lockfile-Format | pnpm-lock.yaml (lesbar) | package-lock.json | yarn.lock | bun.lockb (binär) |
| Phantom-Abhängigkeiten | Verhindert | Möglich | Verhindert (PnP) | Möglich |
| Node.js-Kompatibilität | Vollständig | Vollständig | Gut (Plug'n'Play komplex) | Hoch |
Migration von npm zu pnpm
Die Migration eines bestehenden npm-Projekts zu pnpm ist in der Regel unkompliziert. pnpm kann aus einem vorhandenen package-lock.json eine neue Lockdatei generieren:
# pnpm installieren
npm install -g pnpm
# Im Projektverzeichnis: alte Lockdatei und node_modules entfernen
rm -rf node_modules package-lock.json
# pnpm-Lockdatei erzeugen und Pakete installieren
pnpm import # Konvertiert package-lock.json zu pnpm-lock.yaml
pnpm install
Die offizielle Dokumentation und weitere Details finden sich auf der pnpm-Website. Eine Übersicht aller CLI-Befehle gibt es in der pnpm CLI-Referenz. Das GitHub-Repository ist unter github.com/pnpm/pnpm zu finden.
Häufig gestellte Fragen
- Muss ich für jedes Projekt separat pnpm installieren?
- Nein, pnpm wird global auf dem System installiert und steht dann für alle Projekte zur Verfügung. Der globale Content-Store wird automatisch von allen Projekten gemeinsam genutzt. Mit
corepack enablekann pnpm auch pro Projekt pinned werden. - Kann ich pnpm auf einem CI/CD-System verwenden?
- Ja, pnpm eignet sich hervorragend für CI/CD. Durch das Caching des globalen Stores zwischen Builds lassen sich erhebliche Zeitersparnisse erzielen. GitHub Actions und andere Plattformen haben spezielle Cache-Aktionen für pnpm.
- Was ist der Unterschied zwischen pnpm und Yarn Berry (v2+)?
- Yarn Berry setzt auf Plug'n'Play (PnP), das
node_modulesvollständig ersetzt. Das ist innovativ, bringt aber Kompatibilitätsprobleme mit Paketen mit, die direkt auf das Dateisystem zugreifen. pnpm behält dennode_modules-Standard bei und ist daher kompatibler, während es trotzdem Speicher spart. - Warum nutzen Projekte wie Vue.js pnpm?
- Große Monorepos wie Vue.js oder Vite profitieren massiv von pnpm's Workspace-Funktionen und dem einzigartigen Filter-System. Die Geschwindigkeit bei der Installation und die zuverlässige Isolation von Abhängigkeiten machen pnpm für komplexe Setups zur bevorzugten Wahl.