paint-brush
Warum Sie PNPM und YARN nicht benötigenby@bormando

Warum Sie PNPM und YARN nicht benötigen

Dmitrii Bormotov9m2024/07/23
Read on Terminal Reader

npm ist ein Standardpaketmanager für das **Node.js**-Ökosystem. Es wird mit dem Installationspaket geliefert und ist daher grundsätzlich einsatzbereit, wenn Sie **Node.js** auf Ihrem Computer installieren (oder in einem beliebigen **CI**-Anbieter, wenn Sie **Node.js** dort einrichten). Es ist stabil und seine Geschwindigkeit ist mit anderen Paketmanagern vergleichbar.
featured image - Warum Sie PNPM und YARN nicht benötigen
Dmitrii Bormotov HackerNoon profile picture
0-item

Hallo zusammen!


Sie haben sicher schon Node.js-Projekte gesehen, die unterschiedliche Paketmanager verwenden, beispielsweise:



Ich habe das selbst gesehen und mit all dem oben genannten gearbeitet, aber ich hatte immer eine Frage im Kopf – was bewegt Leute/Teams dazu, yarn oder pnpm statt npm zu verwenden? Was sind die Vorteile? Gibt es irgendwelche Nachteile?


Nun... finden wir es heraus!

Regeln für den Leistungsvergleich

Ich habe beschlossen, npm , yarn und pnpm hinsichtlich ihrer „Geschwindigkeit“ zu vergleichen …


Nachfolgend sehen Sie 3 Maßnahmen:


  1. Erstellen Sie eine Sperrdatei ohne Cache.


  2. Installieren Sie Abhängigkeiten von vorhandenen Sperrdateien ohne Cache.


  3. Installieren Sie Abhängigkeiten von vorhandenen Sperrdateien mit globalem Cache.


Es gibt zwei Arten von Cache:


  1. Weltweit.

    Normalerweise im Home-Verzeichnis des Benutzers gespeichert (zB ~/.yarn/berry/cache ).


  2. Lokal.

    Wird im Projektverzeichnis gespeichert (zB <project-dir>/.yarn ).


Während Nr. 2 und Nr. 3 meiner Erfahrung nach die häufigsten Anwendungsfälle sind, habe ich vorsichtshalber auch Nr. 1 genommen (obwohl das ein seeehr seltener Fall ist).


Als Beispiel für Benchmarks habe ich ein Beispielprojekt von create-react-app verwendet.

npm

Es handelt sich um einen Standardpaketmanager für das Node.js- Ökosystem – was soll man sonst noch dazu sagen? Er wird mit dem Installationspaket geliefert und ist daher grundsätzlich einsatzbereit, wenn Sie Node.js auf Ihrem Computer installieren (oder in einem beliebigen CI- Anbieter, wenn Sie Node.js dort einrichten).


Das ist meiner Meinung nach ein großes „Pro“ – Sie müssen es nicht separat installieren!


Nichts Besonderes – es funktioniert einfach! Und ich habe im Laufe der Jahre keine größeren Fehler gesehen – es scheint ziemlich stabil zu sein und erledigt die Arbeit.


Die Funktionen von npm, die ich bisher verwendet habe:


  1. Abhängigkeiten verwalten (installieren, entfernen, aktualisieren)
  2. Pakete veröffentlichen (privat, öffentlich)
  3. Link-Local-Pakete
  4. Arbeitsbereiche verwalten.

Abhängigkeiten verwalten

npm speichert Abhängigkeiten im Ordner node_modules Ihres Projektstamms. Ziemlich unkompliziert.


ℹ️ package-lock.json speichert Informationen zu Registern für die aufgelisteten Pakete – das ist SEHR praktisch, wenn Sie Pakete aus einem einzigen Bereich haben, d. h. @example-company in verschiedenen Registern (z. B. npm- und GitHub-Pakete ):


package-lock.json-Eintrag


Sehen wir uns nun an, wie die Installationsgeschwindigkeit aussieht …

Generieren Sie package-lock.json ohne Cache

Generieren Sie package-lock.json und installieren Sie Abhängigkeiten ohne Cache


Es dauerte 1 Minute damit npm eine package-lock.json generiert und Abhängigkeiten ohne Cache installiert.


Verwendeter Befehl:

 npm i

Installieren Sie Abhängigkeiten aus package-lock.json ohne Cache

Installieren Sie Abhängigkeiten von package-lock.json ohne Cache


Es dauerte 18 Sekunden damit npm Abhängigkeiten von package-lock.json ohne Cache installiert.


Verwendeter Befehl:

 npm ci

Installieren Sie Abhängigkeiten aus package-lock.json mit globalem Cache

Installieren Sie Abhängigkeiten von package-lock.json mit globalem Cache


Es dauerte 8 Sekunden damit npm Abhängigkeiten von package-lock.json mit globalem Cache installiert.


Verwendeter Befehl:

 npm ci

Arbeitsbereiche verwalten

Ich konnte einen Arbeitsbereich erstellen und Abhängigkeiten für den gesamten Arbeitsbereich auf einmal und für bestimmte Projekte separat verwalten.


Mit anderen Worten: Es erledigt die Arbeit ohne Fehler/Probleme und die offizielle Dokumentation ist ziemlich unkompliziert.


Arbeitsbereichsfunktionen, die ich bisher verwendet habe:


  1. Installieren Sie Abhängigkeiten für alle Projekte innerhalb des Arbeitsbereichs.
  2. Installieren Sie Abhängigkeiten für ein einzelnes bestimmtes Projekt.
  3. Führen Sie rekursiv ein einzelnes Skript für alle Projekte gleichzeitig aus.

Garn

Ehrlich gesagt habe ich einige der Yarn- Funktionen noch nicht oft ausprobiert. Ich meine, ich habe sie bei der Arbeit an einigen Projekten häufig zum „Installieren von Abhängigkeiten“ verwendet, und das war’s auch schon.


yarn wird nicht mit einem Node.js- Installationsprogramm geliefert, Sie müssen es also separat installieren. Das bedeutet, dass in Ihren CI- Pipelines ein zusätzlicher Schritt erforderlich ist – Sie müssen yarn einrichten, bevor Sie Ihre Projektabhängigkeiten installieren.

Abhängigkeiten verwalten

Yarn bietet zwei Ansätze zum Installieren von Abhängigkeiten:


  1. Zero Installs “ (Standard) – erstellt einen .yarn Ordner und listet Pakete in den Dateien yarn.lock und .pnp.cjs auf.


  2. Eine normale Variante – ähnlich wie npm – speichert Abhängigkeiten in node_modules und listet sie in der Datei yarn.lock auf.


ℹ️ Yarn -Lock-Dateien speichern NUR Informationen zu Registrierungen für alle aufgelisteten Pakete, wenn Sie den alten (regulären) Installationsansatz verwenden.


⚠️ Bedenken Sie, dass „ Zero Installs “ Pakete im lokalen Cache zu speichern scheint und Links zu Ihren Sperrdateien bereitstellt:


Paketlinks

Dies kann für Sie wichtig sein, wenn Sie über eine Docker-Datei oder CI- Pipeline verfügen, in der Sie Abhängigkeiten in einer sauberen Umgebung installieren und diese dann in eine andere verschieben möchten (Sie müssen sowohl den .yarn Ordner als auch den lokalen Cache kopieren).


Da der Standardansatz für Yarn jetzt „ Null Installationen “ ist und eine bessere Leistung als der alte Ansatz bietet, werden wir Benchmarks nur mit diesem Ansatz aufzeichnen.

Sperrdateien ohne Cache generieren

Generieren Sie Sperrdateien mit Yarn und installieren Sie Abhängigkeiten


Es dauerte 16,5 Sekunden damit Yarn eine yarn.lock Datei generiert und Abhängigkeiten ohne Cache installiert.


Verwendeter Befehl:

 yarn install

Installieren Sie Abhängigkeiten aus vorhandenen Sperrdateien ohne Cache

Installieren Sie Abhängigkeiten mit dem „Zero Install“-Ansatz und ohne Cache


Es dauerte 11 Sekunden für Yarn, um Abhängigkeiten mit dem „Zero Install“-Ansatz und ohne Cache zu installieren.


Verwendeter Befehl:

 yarn install --frozen-lockfile

Installieren Sie Abhängigkeiten aus vorhandenen Sperrdateien mit globalem Cache


Installieren Sie Abhängigkeiten mit dem „Zero Install“-Ansatz und dem globalen Cache


Es dauerte 8 Sekunden für Yarn, um Abhängigkeiten mit dem „Zero Install“-Ansatz und globalem Cache zu installieren.


Verwendeter Befehl:

 yarn install --frozen-lockfile

Arbeitsbereiche verwalten

Ich konnte einen Arbeitsbereich erstellen und Abhängigkeiten für alle Projekte gleichzeitig und für bestimmte Projekte separat verwalten.


Arbeitsbereichsfunktionen, die ich bisher verwendet habe:


  1. Installieren Sie Abhängigkeiten für alle Projekte innerhalb des Arbeitsbereichs.
  2. Installieren Sie Abhängigkeiten für ein einzelnes bestimmtes Projekt.
  3. Führen Sie rekursiv ein einzelnes Skript für alle Projekte gleichzeitig aus.


Die Dokumentation ist in Ordnung, aber Befehlsnamen und Flags sind etwas verwirrend.


Beispielsweise muss ich dies ausführen, um test im Stammverzeichnis ( . ) und im verschachtelten b2b Projekt auszuführen:


 yarn workspaces foreach -A --include '{.,b2b}' run test


Im Vergleich mit npm :


 npm run test --workspace=b2b --include-workspace-root

pnpm

pnpm ist derzeit ein Hype – viele Unternehmen und Open-Source-Projekte verwenden es .


Genau wie Yarn wird pnpm nicht mit einem Node.js- Installationsprogramm geliefert, Sie müssen es also separat installieren. Das bedeutet, dass in Ihren CI- Pipelines ein zusätzlicher Schritt erforderlich ist: Sie müssen pnpm einrichten, bevor Sie Ihre Projektabhängigkeiten installieren.

Abhängigkeiten verwalten

pnpm gilt als schneller, speicherplatzsparender Paketmanager


Tatsächlich stimme ich der Aussage „Speicherplatzeffizienz“ im Hinblick auf die lokale Verwaltung von Abhängigkeiten zu.


Standardmäßig entfernt pnpm Duplikate gemeinsam genutzter Abhängigkeiten. pnpm erstellt symbolische Links für die Pakete, die in mehreren Abhängigkeiten verwendet werden. Wenn beispielsweise die Pakete a und b Paket c als Abhängigkeit verwenden, speichert pnpm Paket c als einzelne Kopie und erstellt symbolische Links für die Pakete a und b . Auf diese Weise erstellt der Paketmanager keine Hardcopys und spart Speicher auf Ihrer SSD/HDD.


ℹ️ pnpm-lock.yaml speichert keine Informationen zu Registrierungen für die aufgelisteten Pakete.


⚠️ Denken Sie daran, dass pnpm Abhängigkeiten manchmal im globalen Cache speichert, anstatt sie als Projekt zu behalten.

Generieren Sie pnpm-lock.yaml ohne Cache

Generieren Sie pnpm-lock.yaml


Es dauerte 31 Sekunden damit pnpm eine pnpm-lock.yaml generiert und Abhängigkeiten ohne Cache installiert.


Verwendeter Befehl:

 pnpm install

Installieren Sie Abhängigkeiten von pnpm-lock.yaml ohne globalen Cache

Installieren Sie Abhängigkeiten von pnpm-lock.yaml ohne globalen Cache


Es dauerte 16 Sekunden damit pnpm Abhängigkeiten von pnpm-lock.yaml ohne Cache installiert.


Verwendeter Befehl:

 pnpm i --frozen-lockfile


Installieren Sie Abhängigkeiten aus einer vorhandenen Sperrdatei mit globalem Cache

Installieren Sie Abhängigkeiten von pnpm-lock-yaml mit Cache


Es dauerte 5 Sekunden damit pnpm Abhängigkeiten von pnpm-lock.yaml mit globalem Cache installiert.


Verwendeter Befehl:

 pnpm i --frozen-lockfile

Arbeitsbereiche verwalten

Jetzt wird es wirklich interessant …


pnpm hat viele Konfigurationsoptionen, aber einige Kernfunktionen funktionieren einfach nicht!


Sehen wir uns ein paar Fehler an, mit denen ich konfrontiert war:

pnpm install --filter

Es ist wichtig, Abhängigkeiten nur für bestimmte Projekte installieren zu können. Dies ist bei Monorepos sehr nützlich, wenn Sie Pipelines erstellen, die sich auf bestimmte Projekte innerhalb des Arbeitsbereichs beziehen.


Stellen Sie sich beispielsweise vor, Sie hätten in Ihrem Arbeitsbereich:


  • eine Web-App,
  • Backend-Server,
  • Testprojekt (End-to-End-Tests).


Dies sind alles separate npm- Projekte, aber sie sind Teil desselben Repos ☝️


Nun möchten Sie, dass eine Pipeline nur End-to-End-Tests ausführt. Sie benötigen also nur End-to-End-Testabhängigkeiten, richtig?


Nun, das werden Sie nicht tun können – pnpm zwingt Sie, Abhängigkeiten für den gesamten Arbeitsbereich zu installieren!


pnpm install --filter <project-name> sollte nur Abhängigkeiten für ausgewählte Projekte installieren, funktioniert aber nicht.


Es handelt sich um einen ein Jahr alten Fehler, der vor Kurzem mit einem nicht funktionierenden Fix behoben wurde.

rekursive-install=false

pnpm installiert standardmäßig Abhängigkeiten für den gesamten Arbeitsbereich (alle Projekte), wenn Sie pnpm install ausführen


Sie können dieses Verhalten ändern, indem Sie in .npmrc in Ihrem Arbeitsbereichsstamm recursive-install=false festlegen.


ABER es führt einen weiteren Fehler ein, der schon fast 2 Jahre alt ist .

gemeinsam genutzter Arbeitsbereich-Sperrdatei = false

pnpm speichert die Abhängigkeitsliste standardmäßig in einer einzigen Sperrdatei (wie npm und yarn ).


Sie können dieses Verhalten auch ändern, wenn Sie in .npmrc in Ihrem Arbeitsbereichsstamm shared-workspace-lockfile=false festlegen.


Dadurch könnten wir die Arbeitsbereichsfunktion beibehalten und das Flag --ignore-workspace verwenden, um Abhängigkeiten für ein bestimmtes Projekt zu installieren.


Diese Einstellung bringt jedoch einige weitere Probleme mit sich:


  1. eslint und tsc --noEmit werfen in meinen GitHub Actions -Pipelines einen „JavaScript-Heap nicht genügend Arbeitsspeicher“ -Fehler aus.


  2. Einige der Abhängigkeiten werden im globalen Cache gespeichert und in node_modules/.pnpm symbolisch verknüpft.

Ergebnisse des Leistungsvergleichs

#

npm

Garn

pnpm

Generieren einer Sperrdatei

60 Sek.

16,5 Sek.

31 Sek.

Installieren Sie Abhängigkeiten ohne Cache

18 Sek.

11 Sek.

8 Sek.

Installieren Sie Abhängigkeiten mit globalem Cache

8 Sek.

8 Sek.

5 Sek.


Laut dem obigen Benchmark ist npm der langsamste Paketmanager ☝️


Lassen Sie uns diese Ergebnisse jedenfalls interpretieren …

Generieren einer Sperrdatei

Dies ist ein seltener Fall. Normalerweise wird bei der Projektinitialisierung eine Sperrdatei erstellt und dann erweitert, wenn Sie Pakete installieren/aktualisieren.


In Anbetracht dessen scheint es kein besonders wichtiger Faktor zu sein, auf den Sie sich bei der Auswahl eines Paketmanagers verlassen sollten.

Abhängigkeiten installieren

In den meisten Fällen enthalten Ihre Projekte eine bestimmte Liste von Abhängigkeiten und Sie fügen selten etwas hinzu bzw. entfernen es.


Höchstwahrscheinlich werden Sie von Zeit zu Zeit Versionen Ihrer Pakete aktualisieren. Diese Änderungen sind geringfügig und Sie werden die restlichen Pakete aus dem Cache wiederverwenden.


Mit anderen Worten: Der übliche Anwendungsfall ist: Neue Pakete aus der Paketregistrierung abrufen und den Rest aus dem Cache holen.


pnpm (5–8 Sek.) ist fast doppelt so schnell wie npm (8–18 Sek.) mit yarn (8–11 Sek.) in der Mitte.

Abschluss

Fakten

  • pnpm ist tatsächlich ein „schneller und festplatteneffizienter“ Paketmanager – das wird in der aktuellen Rezension ganz klar!


  • Die PNPPM- Arbeitsbereichsfunktion ist fehlerhaft und einige der Fehler sind seit Jahren nicht behoben.


  • sowohl pnpm als auch yarn erfordern eine zusätzliche Einrichtung in CI-Pipelines, während dies bei npm nicht der Fall ist.


  • weder pnpm noch yarn speichern Paketregistrierungsinformationen in ihren Sperrdateien, npm hingegen schon.

Gedanken des Autors

Ich denke, dass pnpm die beste Arbeit leistet, wenn Ihre Anforderung an den Paketmanager so einfach ist wie „nur Abhängigkeiten installieren“.


Obwohl pnpm nicht mit einem vorinstallierten Node.js- Installationsprogramm ausgeliefert wird, lässt es sich mit Corepack oder einer vorhandenen Aktion problemlos in CI-Pipelines einrichten.


Ich bevorzuge npm , weil:


  • es ist stabil (vor allem Arbeitsbereiche),


  • kommt mit Node.js und erfordert kein zusätzliches Setup in der CI-Pipeline,


  • speichert Paketregistrierungen in package-lock.json sodass Sie Abhängigkeiten mit einem einzigen Umfang aus verschiedenen Registrierungen installieren können.


Diese Vorteile überwiegen die Sekunden an Geschwindigkeit und Speicherplatz, die ich mit yarn oder pnpm sparen würde.


Nach welchen Kriterien wählen Sie einen Paketmanager aus? Seien Sie nicht schüchtern und teilen Sie mir Ihre Meinung im Kommentarbereich unten mit! 👇😊