it-swarm.com.de

Warum schreibt "npm install" package-lock.json neu?

Ich habe vor kurzem ein Upgrade auf npm @ 5 durchgeführt. Ich habe jetzt eine package-lock.json-Datei mit allem aus package.json. Ich würde erwarten, dass bei der Ausführung von npm install die Abhängigkeitsversionen aus der Sperrdatei gezogen werden, um festzustellen, was in meinem Verzeichnis node_modules installiert werden soll. Das Seltsame ist, dass es tatsächlich dazu neigt, meine package-lock.json-Datei zu ändern und neu zu schreiben.

Beispielsweise wurde für die Sperrdatei TypeScript auf Version 2.1.6 festgelegt. Nach dem Befehl npm install wurde die Version in 2.4.1 geändert. Das scheint den ganzen Zweck einer Sperrdatei zu zerstören.

Was vermisse ich? Wie bekomme ich, dass npm meine Sperrdatei tatsächlich respektiert?

385
Viper Bailey

Update 3: Wie auch andere Antworten zeigen, wurde der Befehl npm ci in npm 5.7.0 als zusätzliche Möglichkeit eingeführt, um schnelle und reproduzierbare Builds im CI-Kontext zu erreichen. Weitere Informationen finden Sie im Dokumentation und npm Blog .


Update 2: Das Problem zum Aktualisieren und Verdeutlichen der Dokumentation ist GitHub Ausgabe # 18103 .


Update 1: Das unten beschriebene Verhalten wurde in npm 5.4.2 behoben. Das aktuell beabsichtigte Verhalten ist in GitHub Ausgabe # 17979 beschrieben.


Ursprüngliche Antwort: Das Verhalten von package-lock.json wurde in npm 5.1.0 geändert, wie in Ausgabe # 16866 beschrieben. Das Verhalten, das Sie beobachten, ist anscheinend von npm ab Version 5.1.0 beabsichtigt.

Das bedeutet, dass package.jsonpackage-lock.json trumpfen kann, wenn in package.json eine neuere Version für eine Abhängigkeit gefunden wird. Wenn Sie Ihre Abhängigkeiten effektiv festlegen möchten, müssen Sie jetzt die Versionen ohne Präfix angeben. Sie müssen sie beispielsweise als 1.2.0 anstelle von ~1.2.0 oder ^1.2.0 schreiben. Dann ergibt die Kombination von package.json und package-lock.json reproduzierbare Builds. Um es klar zu sagen: package-lock.json alleine sperrt nicht mehr die Abhängigkeiten der Root-Ebene!

Ob diese Entwurfsentscheidung gut war oder nicht, ist fraglich. Aus dieser Verwirrung über GitHub in Ausgabe # 17979 wird laufend diskutiert. (In meinen Augen ist dies eine fragwürdige Entscheidung; zumindest gilt der Name lock nicht mehr.)

Noch eine Randbemerkung: Es gibt auch eine Einschränkung für Registries, die unveränderliche Pakete nicht unterstützen, z. B. wenn Sie Pakete direkt von GitHub statt von npmjs.org abrufen. Weitere Informationen finden Sie in dieser Dokumentation der Paketsperren .

280
jotaen

Ich habe festgestellt, dass es eine neue Version von npm 5.7.1 mit dem neuen Befehl npm ci geben wird, die nur von package-lock.json installiert wird

Der neue Befehl npm ci wird NUR von Ihrer Sperrdatei installiert. Wenn Ihre package.json und Ihre Sperrdatei nicht synchron sind, wird ein Fehler gemeldet.

Es funktioniert, indem wir die node_modules wegwerfen und von Grund auf neu erstellen.

Neben der Garantie, dass Sie nur das bekommen, was sich in Ihrer Lock-Datei befindet, ist es auch viel schneller (2x-10x!) Als npm install, wenn Sie nicht mit node_modules beginnen.

Wie Sie dem Namen entnehmen können, erwarten wir, dass kontinuierliche Integrationsumgebungen ein großer Vorteil sind. Wir erwarten auch, dass die Leute, die die Produktion von Git-Tags durchführen, große Gewinne erzielen werden.

102

Verwenden Sie das neu eingeführte

npm ci

npm ci verspricht großen Teams den größten Nutzen. Wenn Entwickler die Möglichkeit erhalten, sich für eine Paketsperre „abzumelden“, wird eine effizientere Zusammenarbeit zwischen großen Teams gefördert. Die Möglichkeit, genau das zu installieren, was sich in einer Sperrdatei befindet, kann Dutzende, wenn nicht Hunderte von Entwicklerstunden pro Monat einsparen mehr Zeit damit verbringen, erstaunliche Dinge zu bauen und zu versenden.

Einführung von npm ci für schnellere, zuverlässigere Builds

59
Gal Margalit

Kurze Antwort:

  • Wenn package-lock.json existiert, wird package.json überschrieben
  • Wenn package.json geändert wird, wird die package-lock.json überschrieben

Hier ist ein Szenario, das die Dinge erklären könnte (Verified mit NPM 6.3.0)

Sie erklären eine Abhängigkeit in package.json wie:

"depA": "^1.0.0"

Dann machen Sie, npm install, der eine package-lock.json generiert mit:

"depA": "1.0.0"

Wenige Tage später wird eine neuere untergeordnete Version von "depA" veröffentlicht, sagen Sie "1.1.0". Dann gilt Folgendes:

npm ci       # respects only package-lock.json and installs 1.0.0

npm install  # also, respects the package-lock version and keeps 1.0.0 installed 
             # (i.e. when package-lock.json exists, it overrules package.json)

Als Nächstes aktualisieren Sie Ihre package.json manuell folgendermaßen:

"depA": "^1.1.0"

Dann wiederholen Sie:

npm ci      # will try to honor package-lock which says 1.0.0
            # but that does not satisfy package.json requirement of "^1.1.0" 
            # so it would throw an error 

npm install # installs "1.1.0" (as required by the updated package.json)
            # also rewrites package-lock.json version to "1.1.0"
            # (i.e. when package.json is modified, it overrules the package-lock.json)
9

Sie haben wahrscheinlich etwas wie:

"TypeScript":"~2.1.6"

in Ihrem package.json, der von npm auf die neueste Nebenversion aktualisiert wird, in Ihrem Fall 2.4.1

Edit: Frage vom OP

Aber das erklärt nicht, warum "npm install" die Sperrdatei ändert. Ist die Sperrdatei nicht dazu gedacht, einen reproduzierbaren Build zu erstellen? Wenn ja, Unabhängig vom Semver-Wert sollte immer noch der gleiche 2.1.6 .__ verwendet werden. Ausführung.

Antworten:

Hiermit soll der vollständige Abhängigkeitsbaum gesperrt werden. Angenommen, TypeScript v2.4.1 erfordert widget ~v1.0.0. Wenn Sie npm installieren, __. greift widget v1.0.0. Später von Ihrem Entwickler (oder CI-Build) führt eine npm-Installation aus und ruft TypeScript v2.4.1 ab, aber widget wurde aktualisiert zu widget v1.0.1. Jetzt ist Ihr Knotenmodul nicht mehr synchron. Diese ist, was package-lock.json verhindert.

Oder ganz allgemein:

Als Beispiel betrachten 

paket A:

{"Name": "A", "Version": "0.1.0", "Abhängigkeiten": { "B": "<0,1,0"}} 

paket B:

{"Name": "B", "Version": "0.0.1", "Abhängigkeiten": { "C": "<0,1,0"}}

und Paket C:

{"name": "C", "version": "0.0.1"}

Wenn dies die einzigen Versionen sind von A, B und C in der Registrierung verfügbar, dann eine normale npm-Installation A wird installieren:

[email protected] - [email protected] - [email protected] 

Wenn jedoch [email protected] veröffentlicht wird, wird eine neue npm-Installation von A installiert:

[email protected] - [email protected] - [email protected] unter der Annahme, dass die neue Version die Abhängigkeiten von B nicht geändert hat. Natürlich kann die neue Version von B ein neues .__ enthalten. Version von C und beliebig viele neue Abhängigkeiten. Wenn solche Änderungen sind unerwünscht, der Autor von A könnte eine Abhängigkeit von [email protected] ..__ angeben. Wenn jedoch der Autor von A und der Autor von B nicht dieselbe Person sind, gibt es Es gibt keine Möglichkeit für den Autor von A, zu sagen, dass er oder sie nicht hineinziehen will. neu veröffentlichte Versionen von C, wenn sich B nicht geändert hat.


OP Frage 2: Lassen Sie mich sehen, ob ich richtig verstehe. Was du bist besagt, dass die Sperrdatei die Versionen des sekundären .__ angibt. Abhängigkeiten, ist aber dennoch auf das Fuzzy-Matching von package.json .__ angewiesen. um die Abhängigkeiten auf oberster Ebene zu bestimmen. Ist das richtig?

Antwort: Nein. Package-lock sperrt die gesamte Paketstruktur, einschließlich der Root-Pakete, beschrieben in package.json. Wenn TypeScript gesperrt ist Bei 2.4.1 in Ihrem package-lock.json sollte es so bleiben, bis es .__ ist. geändert. Und sagen wir morgen die TypeScript Version 2.4.2. Wenn ich Ihren Zweig auschecke und npm install starte, respektiert npm das Lockfile und installieren Sie 2.4.1.

Mehr zu package-lock.json:

package-lock.json wird automatisch für alle Vorgänge generiert, bei denen npm entweder die node_modules-Struktur oder package.json ändert. Es beschreibt den genauen Baum, der generiert wurde, sodass nachfolgende Installationen unabhängig von den Aktualisierungen der abhängigen Abhängigkeiten identische Bäume generieren können.

Diese Datei soll in Quellrepositorys übernommen werden und dient verschiedenen Zwecken:

Beschreiben Sie eine einzelne Repräsentation eines Abhängigkeitsbaums, sodass garantiert wird, dass Teammitglieder, Bereitstellungen und kontinuierliche Integration genau dieselben Abhängigkeiten installieren.

Stellen Sie Benutzern die Möglichkeit zur Verfügung, "Zeitreise" zu vorherigen Zuständen von node_modules durchzuführen, ohne das Verzeichnis selbst festschreiben zu müssen.

Um die Sichtbarkeit von Baumänderungen durch lesbare Quellsteuerungsdifferenzen zu verbessern.

Und optimieren Sie den Installationsprozess, indem Sie npm zulassen, dass wiederholte Metadaten-Auflösungen für zuvor installierte Pakete übersprungen werden.

https://docs.npmjs.com/files/package-lock.json

6
Matt

Verwenden Sie den Befehl npm ci anstelle von npm install.

"ci" steht für "clean install". Es installiert die Projektabhängigkeiten basierend auf der package-lock.json-Datei anstelle der lenient package.json-Dateiabhängigkeiten.

Es erzeugt identische Builds zu den anderen Teammitgliedern und ist auch viel schneller.

5
Daniel Tonon

Zukünftig können Sie ein --from-lock-file (oder ein ähnliches) Flag verwenden, um only vom package-lock.json zu installieren, ohne es zu ändern. 

Dies ist nützlich für CI-Umgebungen usw., in denen reproduzierbare Builds wichtig sind.

Unter https://github.com/npm/npm/issues/18286 finden Sie Informationen zur Nachverfolgung der Funktion.

5

Es scheint, dass dieses Problem in npm v5.4.2 behoben wurde

https://github.com/npm/npm/issues/17979

(Bis zum letzten Kommentar im Thread scrollen)

Update

Eigentlich behoben in 5.6.0. In 5.4.2 gab es einen plattformübergreifenden Fehler, durch den das Problem weiterhin auftrat.

https://github.com/npm/npm/issues/18712

Update 2

Siehe meine Antwort hier: https://stackoverflow.com/a/53680257/1611058

npm ci ist der Befehl, den Sie bei der Installation vorhandener Projekte verwenden sollten.

3
Daniel Tonon

Auf ihrer Github-Seite gibt es ein offenes Problem: https://github.com/npm/npm/issues/18712

Dieses Problem ist besonders schwerwiegend, wenn Entwickler unterschiedliche Betriebssysteme verwenden.

1
hrdwdmrbl

BEARBEITEN: Der Name "lock" ist ein kniffliger Name, dessen NPM versucht, Yarn einzuholen. Es ist keine gesperrte Datei. package.json ist eine vom Benutzer festgelegte Datei, die, sobald sie "installiert" ist, den Ordnerbaum node_modules erzeugt, und dieser Baum wird dann in package-lock.json geschrieben. Sie sehen also, es ist der umgekehrte Weg - Abhängigkeitsversionen werden wie immer aus package.json abgerufen und package-lock.json sollte package-tree.json heißen.

(hoffe das hat meine Antwort klarer gemacht, nachdem so viele Stimmen abgelaufen sind)


Eine einfache Antwort: package.json hat Ihre Abhängigkeiten wie üblich, während package-lock.json "ein genauer und vor allem reproduzierbarer node_modules-Baum" ist (aus npm docs selbst ).

Was den kniffligen Namen angeht, versucht sein NPM, Yarn einzuholen.

0
Z. Khullah