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?
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.json
package-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 .
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.
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.
Kurze Antwort:
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)
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
erfordertwidget ~v1.0.0
. Wenn Sie npm installieren, __. greiftwidget v1.0.0
. Später von Ihrem Entwickler (oder CI-Build) führt eine npm-Installation aus und ruftTypeScript v2.4.1
ab, aberwidget
wurde aktualisiert zuwidget v1.0.1
. Jetzt ist Ihr Knotenmodul nicht mehr synchron. Diese ist, waspackage-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
. WennTypeScript
gesperrt ist Bei2.4.1
in Ihrempackage-lock.json
sollte es so bleiben, bis es .__ ist. geändert. Und sagen wir morgen dieTypeScript
Version2.4.2
. Wenn ich Ihren Zweig auschecke undnpm install
starte, respektiert npm das Lockfile und installieren Sie2.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.
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.
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.
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.
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.
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.