Jeśli pracujecie z JavaScript od jakiegoś czasu, na pewno macie zainstalowane npm – bo jest domyślnie z Node.js i trudno go uniknąć. Być może używacie też yarna, bo w 2016 roku był naprawdę szybszy od npm i jako pierwszy wprowadził lockfile. Ale pnpm? Przez długi czas był niszowy, a dziś trudno otworzyć dokumentację jakiegokolwiek nowoczesnego narzędzia JS i go nie zobaczyć. Myślę, że warto wyjaśnić skąd ta popularność i czy jest uzasadniona.
Zacznijmy od pnpm
pnpm (skrót od performant npm) rozwiązuje problem, który przez lata był traktowany jako normalny – czyli to, że przy każdym projekcie Node.js na dysku lądują gigabajty tych samych paczek.
Macie 10 projektów, każdy używa Reacta? Bez pnpm na dysku macie 10 kopii Reacta. Przy pnpm – tylko jedną.
Działa to tak, że pnpm utrzymuje jeden globalny store na dysku (~/.pnpm-store), a w node_modules każdego projektu trafiają jedynie dowiązania (symlinki i hard linki) do tego wspólnego miejsca. Efekt jest taki, że instalacja kolejnego projektu, który używa tych samych zależności, jest błyskawiczna – bo pliki już są na dysku, trzeba tylko stworzyć linki.
globalny store (jeden na cały komputer)
└── pliki wszystkich paczek
projekt-A/node_modules/ ← linki do store
projekt-B/node_modules/ ← te same linki, zero duplikacji
Ale to nie jedyna zaleta. pnpm chroni też przed tzw. phantom dependencies — czyli sytuacją, w której używacie w kodzie paczki, której sami nigdy nie zainstalowaliście.
Jak to możliwe? npm i yarn spłaszczają strukturę node_modules — jeśli Wasza zależność A wewnętrznie używa lodasha, to lodash ląduje bezpośrednio w node_modules i nic nie stoi na przeszkodzie żebyście sami go zaimportowali, nawet jeśli nie ma go w Waszym package.json. Działa? Działa. Problem pojawia się gdy aktualizujecie zależność A i ona przy okazji przestaje używać lodasha — Wasz kod przestaje działać, a przyczyna jest zupełnie nieoczywista.
pnpm tego nie dopuszcza. W node_modules widzicie tylko to co sami zadeklarowaliście.
A npm i yarn?
Żeby było jasne jak pnpm się wyróżnia – warto zobaczyć skąd w ogóle pochodzi ta trójka.
npm
npm jest od zawsze. Lata temu miał poważne problemy – był wolny, nie miał domyślnego lockfile’a, a struktura node_modules była płaska i chaotyczna. Z czasem te rzeczy poprawiono (package-lock.json pojawił się w wersji 5), ale główny problem pozostał: każdy projekt dostaje swoje własne kopie wszystkich paczek. Na większym monorepo potrafi to być kilkanaście GB śmieci.
yarn
Yarn stworzył Facebook w 2016 roku, żeby poprawić to co w npm nie działało. I w swoim czasie był znaczącym krokiem naprzód – równoległe pobieranie, cache, yarn.lock zanim npm miał swój lockfile.
Yarn Berry (czyli v2 i wyżej) poszedł jednak w dość radykalną stronę – Plug’n’Play, które całkowicie pozbywa się node_modules na rzecz jednego pliku .pnp.cjs. Idea fajna, ale w praktyce wiele narzędzi miało z tym problemy i migracja bywała uciążliwa. Część społeczności po prostu odpuściła i… przeszła do pnpm.
Porównanie w pigułce
| npm | yarn | pnpm | |
|---|---|---|---|
| 🚀 Szybkość instalacji | średnia | dobra | najlepsza |
| 💾 Miejsce na dysku | dużo | dużo | mało |
| 👻 Phantom dependencies | tak | tak | nie |
| 🏗️ Monorepo (workspaces) | OK | OK | świetne |
| 🌍 Ekosystem | największy | duży | rosnący |
| 🔒 Lockfile | package-lock.json | yarn.lock | pnpm-lock.yaml |
Dlaczego pnpm nagle jest wszędzie?
Kilka rzeczy złożyło się na to jednocześnie.
Po pierwsze – monorepo stały się standardem. Przy dziesiątkach pakietów w jednym repo, oszczędności miejsca i czasu instalacji są naprawdę odczuwalne. pnpm ma wsparcie dla workspaces, które działa po prostu dobrze.
Po drugie – Vite, Astro, SolidJS i inne popularne narzędzia albo domyślnie polecają pnpm, albo same go używają. Jak zaczynasz nowy projekt z Vite i patrzysz na dokumentację, widzisz pnpm create vite. I tak to się kręci.
Po trzecie – Yarn Berry się nie przyjął. Nie wszystkim odpowiadała migracja do PnP i część deweloperów po prostu skończyła z pnpm jako alternatywą, która nie wymaga tak dużego przestawienia myślenia.
I po czwarte – CI/CD. Każdy menedżer paczek można cache’ować w pipeline’ach i każdy daje jakiś zysk. Ale pnpm ma tu naturalną przewagę szczególnie w monorepo — zamiast utrzymywać wiele kopii tych samych paczek, wszystkie pakiety współdzielą jeden store. Wystarczy go raz przywrócić z cache’a, a pnpm install sprowadza się do błyskawicznego tworzenia linków, bez pobierania czegokolwiek z sieci.
Jak zacząć?
Instalacja jest prosta:
npm install -g pnpm
Albo przez corepack (wbudowany w Node.js):
corepack enable
corepack prepare pnpm@latest --activate
A potem zamiast npm install po prostu: pnpm install
Podsumowanie
Jeśli zaczynasz nowy projekt – pnpm to aktualnie bardzo dobry wybór. Jeśli masz stary projekt i zastanawiasz się czy warto migrować – lockfile można wygenerować od nowa, a sama migracja to w większości przypadków zmiana jednego polecenia w skryptach.
Jedyne kiedy zostałabym przy npm to projekt z bardzo specyficznymi wymaganiami lub sytuacja, gdzie część teamu po prostu nie chce zmieniać przyzwyczajeń. Ale to już bardziej problem ludzki niż techniczny 😄



