Befreie uns aus der Abhängigkeitshölle
Die meisten modernen Dienste und Anwendungen haben eine Masse von Abhängigkeiten, die in einem ständig wachsenden Ordner node-modules
leben. Im Allgemeinen werden viele dieser Bibliotheken aktiv gepflegt, geändert und aktualisiert. Wenn Ihre Abhängigkeiten schlecht verwaltet werden, können Sie sich schnell in der Abhängigkeitshölle wiederfinden.
Wenn Sie mit npm nicht vertraut sind, lesen Sie es hier, bevor Sie weiter lesen
🛒 Grocery Shopping
Wenn Sie eine Knotenanwendung starten, wird einer der ersten Schritte ausgeführt npm install
. Wenn Sie dies ausführen, sucht node in der Basis Ihres Projekts nach einer Datei mit dem Namen package.json
. Wenn diese Datei gefunden wird, wird der Abschnitt dependency
als eine Art „Einkaufsliste“ verwendet, um „Zutaten“ (Codebits) zu sammeln, die Ihre Anwendung benötigt.
Das „Lebensmittelgeschäft“ ist in diesem Fall etwas, das npm registry
nennt. Standardmäßig sucht Ihre Knoten-App in der öffentlichen npm-Registrierung nach diesen Paketen, in der sich fast alles befindet, was Sie benötigen (private Registries können für proprietären Code und so weiter erstellt werden). Wenn das Paket in der Registrierung gefunden wird, legt node diese „Zutat“ in ein node_modules
-Verzeichnis an der Basis Ihres Projekts.
Es ist wichtig zu beachten, dass Pakete, die Sie benötigen, möglicherweise eine eigene „Einkaufsliste“ haben (Paket.json), und alle diese verschachtelten Abhängigkeiten müssen aufgelöst werden, bevor Ihre App zur nächsten Abhängigkeit in ihrem eigenen Paket übergeht.json.
⬆️ Versionen, 🥕 Carets und 🃏 Platzhalter
Die Versionen Ihrer Abhängigkeiten sind im Allgemeinen so etwas wie v1.3.5
. Dies wird semantische Versionierung oder semver genannt. Bei semver stellen die Zahlen Änderungen am Code mit unterschiedlichem Schweregrad dar – MAJOR.MINOR.PATCH
.
Aus ihren Dokumenten –
Hauptversion, wenn Sie inkompatible API-Änderungen vornehmen,
Nebenversion, wenn Sie Funktionen abwärtskompatibel hinzufügen, und
PATCH-Version, wenn Sie abwärtskompatible Fehlerbehebungen vornehmen.
In diesem Sinne möchten viele Leute ihre App automatisch mit allen neuen Dingen aktualisieren, die ihre Abhängigkeiten in neueren, nicht unterbrechenden Änderungen enthalten könnten.
Das Voranstellen mit Tilde
~
gibt Ihnen alle neuenPATCH
Updates, aber nicht Major oder Minor. So könnte~1.3.1
1.3.9
installieren, aber nicht1.4.0
Das Voranstellen mit caret
^
gibt Ihnen alle neuenPATCH
undMINOR
Versionen, aber nicht major. Also^1.3.1
könnte1.4.9
installieren, aber nicht1.5.0
Schauen wir uns den Abhängigkeitsbaum unseres Beispielcodes an:
my-breakfast | | milk | |coffee-script
Ok, eher wie ein Stock, aber hoffentlich ist die Abhängigkeitskette klar. Unser Paket.json erfordert die Version v0.5.0
speziell von milk
, aber milk erfordert coffee-script
irgendwo von 0.9.6
– 1.0.0
. npm install
ausgeführt wird, entwickeln wir unsere App, alles ist hunky-dory.
📼 Lassen Sie uns nun 2 Monate vorspulen. Jemand findet Ihr Projekt und möchte einen Beitrag leisten. Sie verzweigen und klonen Ihr Repo, führen npm install
, aaaaund es funktioniert nicht. „Aber es funktionierte auf meiner Maschine!“ du weinst. Als Ihr Mitarbeiter die Knotenmodule installierte, wurde ihm eine bestimmte Version von milk
garantiert, aber er erhielt eine andere Version von coffee-script
, da milk
Paket ist.json verwendet semver.
🗿 Setzen Sie Ihre Abhängigkeiten in Stein
Eine Lösung hierfür ist die Verwendung einer package-lock.json
-Datei. Diese Datei gibt Ihnen eine sehr genaue Kontrolle über die Versionen jeder Abhängigkeit, die Sie installieren. Wenn Ihr package.json
wie die Einkaufsliste ist, dann ist Ihr package-lock.json
wie ein Budget. Sie können Müsli haben, aber es wird eine Handelsmarke statt Cap’n Crunch sein. Diese Spezifität verläuft in jedem Zweig Ihres Abhängigkeitsbaums. Sie müssen ein package.json
haben, wenn Sie eine Sperrdatei verwenden möchten (das package.json
macht viel mehr als nur Abhängigkeitsverwaltung, das ist nur der Fokus dieses Beitrags).
🎁 Einwickeln
Ich persönlich bin der Meinung, dass immer eine package-lock.json
-Datei verwendet werden sollte (in neueren Versionen von npm wird sie tatsächlich automatisch generiert). Es macht einfach alles zuverlässiger in Umgebungen und Bereitstellungen. Hier sind einige letzte kleine Nuggets, die hoffentlich helfen, wenn es um Abhängigkeiten geht:
-
npm install --save
aktualisiert automatisch Ihre Sperrdatei und Ihr Paket.json mit diesem Paket. -
npm ci
anstelle von nurnpm install
erstellt Ihre Knotenmodule automatisch neu und erstellt sie aus Ihrer Sperrdatei. Es ist ein wirklich hilfreicher Befehl für CI / CD und im Allgemeinen am besten zusammen mit einer Lockdatei zu verwenden. - Für größere Projekte und super robuste Abhängigkeiten schauen Sie sich Docker und Container an. Es kann fast wie eine virtuelle Maschine funktionieren, die Ihren Code und seine Abhängigkeiten perfekt enthält und geklont wird, um sie in verschiedene Umgebungen zu befördern. Hoffentlich haben Sie am Ende viel weniger Probleme mit der Art „Es hat auf meinem Computer funktioniert“.