Dlaczego pnpm instaluje szybciej niż npm: magazyn, linki i ścisła struktura node_modules
pnpm przewyższa npm pod względem szybkości instalacji dzięki użyciu przechowalni adresowej, łączy bezpośrednich zamiast kopii oraz ścisłego zarządzania folderem node_modules za pomocą symlińków, które omijają kosztowne operacje przenoszenia plików.
Po przeniesieniu repozytorium z npm na pnpm czas instalacji często znacznie się skraca. Ten spadek nie jest wytworem wyobraźni. pnpm został stworzony, aby rozwiązać problemy z wydajnością i przestrzenią przechowywania charakterystyczne dla klasycznych instalacji w npm, a oba narzędzia przechowują pakiety w tak różny sposób, że różnica szybkości wynika z zmiany architektonicznej, a nie z drobnego dostosowania.
Poniższe sekcje wyjaśniają, dlaczego pnpm ma tendencję do przewagi, szczególnie gdy aplikacje i monorepo stają się większe.
1. Przechowywanie adresowane treścią zamiast duplikowanych plików
Główna przewaga wynika z sposobu przechowywania pakietów na dysku. W npm każdy projekt posiada własną strukturę plików wszystkich zależności w katalogu node_modules. Dlatego aplikacje, które wszystkie potrzebują lodash, przechowują dziesięć oddzielnych kopii tego pakietu na dysku.
pnpm utrzymuje jeden globalny magazyn adresowalny według treści dla całego systemu. Każda wersja zajmuje tam pojedynczą pozycję; projekt, który jej potrzebuje, otrzymuje od tego magazynu łącza stałe (lub referencje typu copy-on-write) do swojego lokalnego katalogu node_modules. Konsekwencje tego są następujące:
- Pomijane ponowne pobieranie plików, gdy magazyn już zawiera daną wersję
- Pomijane ponowne zapisywanie bajtów, które już istnieją na dysku
- Znacznie mniejsze zużycie przestrzeni, gdy wiele projektów dzieli się bibliotekami
Ponieważ proces instalacji polega głównie na operacjach we/wy z dyskiem, eliminacja powtarzających się zapisów sprawia, że większość opóźnień znika.
2. Łącza stałe i symbole linków zamiast kopiowania
Proces install w npm kopiuje pliki pakietów do katalogu node_modules. Kopiowanie tysięcy plików w złożonej strukturze drzewa jest kosztowne.
pnpm preferuje hard links z globalnego sklepu do projektu, a także symlinks, które kształtują strukturę projektu tak, by odpowiadała grafowi zależności. Link jest w praktyce tańszy niż kopia: system operacyjny rejestruje kolejny wskaźnik do tych samych bloków zamiast je kopiować.
3. Efektywne przechowywanie w pamięci podręcznej między projektami
npm również przechowuje pliki po ich pobraniu, ale mimo to rozszerza i kopiuje je z tej pamięci podręcznej do każdego projektu. W modelu sklepu pnpm, gdy jakaś wersja istnieje już gdziekolwiek na komputerze, jej umieszczenie w zupełnie nowym projekcie odbywa się niemal natychmiast — bez dodatkowego pobierania i z minimalną ilością przetwarzania.
To zachowanie jest szczególnie istotne w sytuacjach, gdy:
- Przechodzimy między gałęziami, które używają różnych zestawów zależności
- Zarządzamy kilkoma repozytoriami, które dzielą wspólne biblioteki
- Uruchamiamy zadania CI, które przywracają wspólny sklep pomiędzy różnymi budowami
4. Struktura node_modules, która nie jest spłaszczona i unika dodatkowej pracy przy rozwiązywaniu konfliktów
Stare wersje npm spłaszczały katalog node_modules, aby zmniejszyć duplikacje, ale ta strategia wiąże się z własnymi kosztami: wymaga intensywnych operacji rozwiązywania, by ustalić, gdzie każdy pakiet powinien się znaleźć bez konfliktów.
pnpm utrzymuje ściśłą, powiązaną sygnaturami strukturę node_modules, dzięki czemu pakiet widzi tylko te zależności, które sam deklarował (brak przypadkowych, niepotrzebnych importów). Bezpieczniejsze rozwiązywanie konfliktów to nie jedyne korzyści – pnpm unika również kosztownego planowania operacji przenoszenia pakietów przez npm, co zmniejsza obciążenie procesora podczas instalacji.
5. Operacje równoległe
pnpm planuje wykonywanie kroków rozwiązywania konfliktów, pobierania pakietów i tworzenia powiązań równocześnie, gdy tylko to możliwe, bardziej agresywnie niż typowe podejście npm. Połączenie tej równoległości z mechanizmem link-instead-of-copy znacznie skraca czas wykonywania zadań, szczególnie w przypadku drzew z bardzo złożonymi grafami zależności.
6. Wpływ w rzeczywistym świecie rośnie wraz z rozmiarem projektu
W przypadku prostego aplikacji składającej się z kilku pakietów różnica może wydawać się niewielka. Zaleta ta wzrasta wraz z:
- Monorepo, w których liczne pakiety współkorzystają z tych samych bibliotek
- Zespołami, które zarządzają kilkoma produktami opartymi na wspólnych zależnościach
- Procesami CI/CD, które są instalowane wielokrotnie przy każdym budowaniu
- Wielkimi drzewami zależności typowymi dla nowoczesnych stacków frontendowych
W takich warunkach czas instalacji poprzez przechowywanie i łączenie plików, który kiedyś trwał minuty w npm, może skrócić się do kilku sekund.
7. Oszczędność miejsca na dysku to efekt uboczny, a nie tylko dodatek
Szybkość jest kluczowa, ale ten sam projekt pomaga również w zarządzaniu pamięcią. Ponieważ paczki nie są klonowane dla każdego projektu, grupy często oszczędzają gigabajty. Na wolniejszych dyskach mniejsza ilość przetwarzanych danych również przyczynia się do zwiększenia prędkości działania jako efekt uboczny.
Szybka analogia
Pomyśl o npm jako o bibliotece, która robi kopie tego samego tytułu dla każdego korzystającego. pnpm to biblioteka, w której wszyscy dzielą się jedną półką, a każdy czytelnik otrzymuje zakładkę do wspólnej kopii. Robienie kserokopii wymaga czasu i papieru; wskazywanie na istniejący egzemplarz jest niemal bezkosztowe.
Wniosek
Przewaga pnpm nad npm nie polega na drobnych ulepszeniach wizualnych. Polega ona na nowym podejściu do zarządzania pamięcią i łączeniem plików: unikanie dublowanych pobierania, preferowanie linków zamiast kopii oraz pomijanie niepotrzebnych operacji. Instalacje – często najwolniejszy etap w procesach pracy z interfejsem użytkownika – stają się szybszymi i bardziej efektywnymi krokami.
Dla zespołów pracujących nad kilkoma projektami lub posiadających monorepo, przyjęcie pnpm to jeden z najprostszych sposobów poprawy zarówno czasu instalacji, jak i zużycia dysku.