Abschnitt 5 · Lektion 4
Lockfile und node_modules
Nach dem ersten npm install liegen zwei neue Dinge in deinem Projekt: der Ordner node_modules und
die Datei package-lock.json. Genau eines davon gehört ins Repository.
Die Frage „committe ich das Lockfile?” wird in jedem Team einmal gestellt und selten begründet beantwortet. Hier ist die Begründung.
Zwei Dateien, zwei Aufgaben
Die package.json sagt, was ungefähr gebraucht wird. Dort steht ^1.6.9, also ein Bereich. Sie
ist von Menschen geschrieben und für Menschen lesbar.
Die package-lock.json sagt, was genau installiert war. Nicht nur deine direkten Pakete, sondern
auch deren Pakete und deren Pakete, jeweils mit der exakten Version und einer Prüfsumme. Sie wird von
npm geschrieben und ist nicht zum Lesen gedacht.
Der Unterschied wird an einem Beispiel klar. In deiner package.json steht ^1.6.9. Du installierst
heute und bekommst 1.6.9. Dein Kollege installiert nächsten Monat und bekommt 1.7.2, weil die
inzwischen erschienen ist und in den Bereich passt. Ihr habt beide dieselbe package.json und
trotzdem verschiedenen Code.
Mit Lockfile bekommt er 1.6.9, genau wie du.
Warum node_modules nicht ins Repository gehört
{
"name": "schlank",
"version": "1.0.0",
"type": "module",
"private": true,
"dependencies": {
"slugify": "^1.6.9"
}
} Bei slugify sieht die Welt harmlos aus. Ein Paket, keine weiteren Abhängigkeiten, ein Eintrag in
node_modules.
{
"name": "beispiel",
"version": "1.0.0",
"type": "module",
"private": true,
"dependencies": {
"express": "^5.2.1",
"slugify": "^1.6.9"
}
} Und jetzt dasselbe mit express dazu. Aus zwei Einträgen werden fast siebzig Pakete, denn jedes
Paket bringt mit, was es selbst braucht: npm install meldete beim letzten Nachzählen added 69 packages, und im Ordner node_modules liegen danach 66 Verzeichnisse. Dass die beiden Zahlen
auseinandergehen, hat einen harmlosen Grund: Ein paar Pakete brauchen eine eigene Fassung von etwas,
das es oben schon gibt, und legen sie in ihrem eigenen node_modules ab. Auf deinem Rechner kannst
du beides nachsehen, npm ls zeigt die oberste Ebene und npm ls --all den ganzen Baum.
Das ist der erste Grund: node_modules sind schnell zehntausende Dateien. Sie im Repository zu
führen macht jeden Klon langsam und jeden Diff unlesbar.
Der zweite Grund wiegt schwerer: Manche Pakete enthalten kompilierte Teile, die zum Betriebssystem passen müssen. Was auf deinem Rechner liegt, läuft auf dem Server vielleicht nicht.
Also: node_modules in die .gitignore, das Lockfile ins Repository. Der Ordner lässt sich
jederzeit aus den beiden Dateien wiederherstellen, andersherum geht es nicht.
npm install gegen npm ci
Es gibt zwei Befehle zum Installieren, und sie tun verschiedene Dinge.
npm install liest die package.json, sucht passende Versionen und darf das Lockfile ändern.
Findet es eine neuere Version, die in deinen Bereich passt, nimmt es sie und schreibt das fest. Das
ist beim Entwickeln richtig.
npm ci liest das Lockfile und nimmt es wörtlich. Es installiert exakt die Versionen, die
dortstehen, und ändert nichts. Passen package.json und Lockfile nicht zusammen, bricht es mit einem
Fehler ab, statt sich etwas auszudenken.
Dazu löscht npm ci ein vorhandenes node_modules vorher komplett. Es baut also immer von vorn auf,
statt auf Resten aufzusetzen.
Auf einem Server und in jeder CI-Pipeline läuft npm ci. Zwei Deployments desselben Commits
installieren damit denselben Code, und das ist die ganze Idee dahinter.
Der Name kommt von Continuous Integration, aber der Befehl ist überall dort richtig, wo eine Installation reproduzierbar sein soll.
„Bei mir läuft es”
Wenn dir jemand diesen Satz sagt und im Projekt liegt kein Lockfile, hast du die Erklärung meistens schon gefunden.
Ohne Lockfile ist jede Installation ein neuer Wurf. Es ist nicht einmal nötig, dass jemand etwas falsch gemacht hat: Es reicht, dass zwischen zwei Installationen irgendwo im Baum eine neue Patch-Version erschienen ist. Und weil in diesem Baum leicht siebzig Pakete hängen, passiert das ständig.
Deshalb bekommt das Lockfile bei einem Merge-Konflikt auch nicht die Behandlung „ich nehme mal meine
Version”. Man löst den Konflikt in der package.json, wirft das Lockfile weg und lässt es neu
erzeugen.
Zum Mitnehmen
Das Lockfile gehört ins Repository, node_modules nicht. Und auf einem Server läuft npm ci, nicht npm install.
Jetzt du
Basis Konto, kostenlosZu dieser Lektion gehört eine Aufgabe. Du schreibst den Code selbst, und nach jedem Lauf sagt dir eine Prüfliste, was schon stimmt.
Dafür brauchst du das Basis Konto. Es kostet nichts, und ein Passwort gibt es auch nicht.
In diesem Kurs läuft dein Code auf einem Server. Dafür hat das Basis Konto 1 Stunde im Monat, mehr Zeit gibt es mit dem Premium Konto.
Was in dieser Lektion steckt
-
Artikel mit 2 Beispielen zum Ausprobieren
Steht hier, ohne Konto lesbar.
-
Aufgabe, auf dem Server geprüft
Öffnet sich mit dem Basis Konto.