Der Autor des Materials, dessen Übersetzung wir heute veröffentlichen, sagt, dass eines der Probleme, mit denen sich Programmierer befassen müssen, darin besteht, dass ihr Code für sie funktioniert und jemand anderem Fehler gibt. Dieses Problem, möglicherweise eines der häufigsten, entsteht aufgrund der Tatsache, dass verschiedene Abhängigkeiten, die das Programm verwendet, in den Systemen des Erstellers und Benutzers des Programms installiert sind. Um diesem Phänomen entgegenzuwirken, existieren in den
Garn- und
npm- Paketmanagern sogenannte Sperrdateien. Sie enthalten Informationen zu den genauen Versionen der Abhängigkeiten. Der Mechanismus ist nützlich, aber wenn jemand ein Paket entwickelt, das in npm veröffentlicht werden soll, sollte er keine Sperrdateien verwenden. Dieses Material widmet sich der Geschichte, warum dies so ist.

Das Wichtigste auf den Punkt gebracht
Sperrdateien sind äußerst nützlich, wenn Sie Node.js-Anwendungen wie Webserver entwickeln. Wenn Sie jedoch über das Erstellen einer Bibliothek oder eines Befehlszeilentools mit dem Ziel der Veröffentlichung in npm sprechen, müssen Sie wissen, dass Sperrdateien in npm nicht veröffentlicht werden. Wenn diese Dateien während der Entwicklung verwendet werden, verwenden der Ersteller des npm-Pakets und diejenigen, die dieses Paket verwenden, unterschiedliche Versionen der Abhängigkeiten.
Was ist eine Sperrdatei?
Die Sperrdatei beschreibt den vollständigen Abhängigkeitsbaum in der Form, die er während der Arbeit am Projekt erhalten hat. Diese Beschreibung enthält auch verschachtelte Abhängigkeiten. Die Datei enthält Informationen zu bestimmten Versionen der verwendeten Pakete. Im npm-Paketmanager werden solche Dateien in yarn -
yarn.lock
als
package-lock.json
yarn.lock
. In beiden Managern befinden sich diese Dateien im selben Ordner wie
package.json
.
So könnte
package-lock.json
aussehen.
{ "name": "lockfile-demo", "version": "1.0.0", "lockfileVersion": 1, "requires": true, "dependencies": { "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "requires": { "color-convert": "^1.9.0" } }, "chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } } } }
Hier ist ein Beispiel für eine
yarn.lock
Datei. Es ist nicht wie
package-lock.json
, enthält jedoch ähnliche Daten.
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. # yarn lockfile v1 ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== dependencies: color-convert "^1.9.0" chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== dependencies: ansi-styles "^3.2.1" escape-string-regexp "^1.0.5" supports-color "^5.3.0"
Beide Dateien enthalten einige wichtige Abhängigkeitsinformationen:
- Die genaue Version jeder installierten Abhängigkeit.
- Abhängigkeitsinformationen für jede Abhängigkeit.
- Informationen zum heruntergeladenen Paket, einschließlich der Prüfsumme zur Überprüfung der Integrität des Pakets.
Wenn alle Abhängigkeiten in der Sperrdatei aufgeführt sind, warum fügen sie dann auch Informationen zu
package.json
? Warum werden zwei Dateien benötigt?
Vergleich von package.json und Sperrdateien
Der Zweck des
dependencies
der Datei
package.json
besteht darin, die Projektabhängigkeiten
package.json
, die installiert werden müssen, damit sie ordnungsgemäß funktionieren. Dies beinhaltet jedoch keine Informationen über die Abhängigkeiten dieser Abhängigkeiten. Abhängigkeitsinformationen können genaue Paketversionen oder einen bestimmten Versionsbereich enthalten, der gemäß den Regeln der
semantischen Versionierung angegeben wurde . Bei Verwendung des Npm- oder Garnbereichs wird die am besten geeignete Version des Pakets ausgewählt.
Angenommen, der Befehl
npm install
wurde ausgeführt, um die Abhängigkeiten eines bestimmten Projekts zu installieren. Während des Installationsprozesses nahm npm geeignete Pakete auf. Wenn Sie diesen Befehl nach einer Weile erneut ausführen und während dieser Zeit neue Versionen von Abhängigkeiten freigegeben werden, kann es durchaus vorkommen, dass beim zweiten Mal andere Versionen der im Projekt verwendeten Pakete geladen werden. Wenn Sie beispielsweise eine Abhängigkeit wie
twilio
mit dem
npm install twilio
der folgende Eintrag im Abschnitt "
dependencies
" der Datei
package.json
:
{ "dependencies": { "twilio": "^3.30.3" } }
Wenn Sie sich die
Dokumentation zur semantischen Versionierung von npm ansehen, sehen Sie, dass das Symbol
^
angibt, dass eine beliebige Version des Pakets geeignet ist, deren Anzahl größer oder gleich 3.30.3 und kleiner als 4.0.0 ist. Wenn das Projekt keine Sperrdatei enthält und eine neue Version des Pakets freigegeben wird,
yarn install
npm install
oder
yarn install
install diese neue Version des Pakets automatisch. Die Informationen in
package.json
werden nicht aktualisiert. Bei Verwendung von Sperrdateien sieht alles anders aus.
Wenn npm oder yarn die entsprechende Sperrdatei findet, werden Pakete basierend auf dieser Datei und nicht auf
package.json
. Dies ist beispielsweise besonders nützlich, wenn Sie CI-Systeme (Continuous Integration) auf Plattformen verwenden, auf denen Sie einen einheitlichen Betrieb von Code und Tests in einer Umgebung sicherstellen müssen, deren Eigenschaften im Voraus bekannt sind. In solchen Fällen können Sie beim Aufrufen der entsprechenden Paketmanager spezielle Befehle oder Flags verwenden:
npm ci # , package-lock.json yarn install --frozen-lock-file # , yarn.lock,
Dies ist äußerst nützlich, wenn Sie ein Projekt wie eine Webanwendung oder einen Server entwickeln, da Sie in einer CI-Umgebung das Benutzerverhalten simulieren müssen. Wenn wir eine Sperrdatei in das Projekt-Repository aufnehmen (z. B. mit Git-Tools erstellt), können wir daher sicher sein, dass jeder Entwickler, jeder Server, jedes Code-Building-System und jede CI-Umgebung dieselben Versionen verwendet Abhängigkeiten.
Warum nicht dasselbe tun, wenn Sie Bibliotheken oder andere Softwaretools in der npm-Registrierung veröffentlichen? Bevor wir diese Frage beantworten, müssen wir darüber sprechen, wie das Veröffentlichen von Paketen funktioniert.
Paketveröffentlichungsprozess
Einige Entwickler glauben, dass das, was in npm veröffentlicht wird, genau das ist, was im Git-Repository gespeichert ist oder was das Projekt nach Abschluss der Arbeit daran wird. Dies ist eigentlich nicht der Fall. Beim Veröffentlichen eines Pakets ermittelt npm
package.json
des
.npmignore
in der Datei
package.json
und der Datei
.npmignore
, welche Dateien veröffentlicht werden
.npmignore
. Wenn nichts davon erkannt werden kann, wird die
.gitignore
Datei verwendet. Außerdem werden einige Dateien immer veröffentlicht, andere nie. Was diese Dateien sind, finden Sie
hier . Beispielsweise ignoriert npm immer den Ordner
.git
.
Danach nimmt npm alle entsprechenden Dateien und
packt sie mit dem Befehl
npm pack
in eine
tarball
Datei. Wenn Sie sich ansehen möchten, was genau in eine solche Datei gepackt ist, können Sie den Befehl
npm pack --dry-run
im Projektordner
npm pack --dry-run
und die Liste der Materialien in der Konsole
npm pack --dry-run
.
Npm pack - Befehlsausgabe trocken ausführenDie resultierende
tarball
Datei wird dann in die npm-Registrierung hochgeladen. Wenn Sie den
npm pack --dry-run
Sie darauf achten, dass eine Datei
package-lock.json
im Projekt nicht in der Tarball-Datei enthalten ist. Dies liegt daran, dass diese Datei gemäß den npm-
Regeln immer ignoriert wird.
Das Ergebnis ist, dass die Datei
package-lock.json
nicht beteiligt ist, wenn jemand das Paket eines anderen installiert. Was sich in dieser Datei befindet, das der Paketentwickler hat, wird bei der Installation des Pakets durch eine andere Person nicht berücksichtigt.
Dies kann durch unglücklichen Zufall zu dem Problem führen, über das wir am Anfang gesprochen haben. Im Entwicklersystem funktioniert der Code einwandfrei und in anderen Systemen führt er zu Fehlern. Tatsache ist jedoch, dass der Projektentwickler und diejenigen, die das Projekt verwenden, unterschiedliche Versionen der Pakete verwenden. Wie kann ich das beheben?
Ablehnung von Sperrdateien und Verwendung von Technologie-Schrumpffolie
Zuerst müssen Sie verhindern, dass Sperrdateien in das Projekt-Repository aufgenommen werden. Wenn Sie git verwenden, müssen Sie Folgendes in Ihre
.gitignore
Projektdatei
.gitignore
:
yarn.lock package-lock.json
In der
yarn.lock
heißt es, dass
yarn.lock
zum Repository hinzugefügt werden muss, auch wenn es um die Entwicklung der Bibliothek geht, die Sie veröffentlichen
yarn.lock
. Wenn Sie jedoch möchten, dass Sie und Ihre Bibliotheksbenutzer mit demselben Code arbeiten, würde ich empfehlen,
yarn.lock
in die
.gitignore
Datei aufzunehmen.
Sie können die automatische Erstellung der Datei
package-lock.json
deaktivieren,
.npmrc
Datei
.npmrc
mit dem folgenden Inhalt zum Projektordner
.npmrc
:
package-lock=false
Wenn Sie mit Garn arbeiten, können Sie den
yarn install --no-lockfile
, mit dem Sie das Lesen der Datei
yarn.lock
deaktivieren können.
Die Tatsache, dass wir die Datei
package-lock.json
, bedeutet jedoch nicht, dass wir keine Informationen über Abhängigkeiten und verschachtelte Abhängigkeiten erfassen können. Es
gibt eine andere Datei namens
npm-shrinkwrap.json
.
Im Allgemeinen ist dies
dieselbe Datei wie
package-lock.json
. Sie wird mit dem
npm shrinkwrap
. Diese Datei wird in die npm-Registrierung aufgenommen, wenn das Paket veröffentlicht wird.
Um diesen Vorgang zu automatisieren, kann der
npm shrinkwrap
als Prepack-Skript zum
package.json
Datei package.json hinzugefügt werden. Sie können den gleichen Effekt mit dem Git-Commit-Hook erzielen. Auf diese Weise können Sie sicher sein, dass in Ihrer Entwicklungsumgebung, in Ihrem CI-System und den Benutzern Ihres Projekts dieselben Abhängigkeiten verwendet werden.
Es ist erwähnenswert, dass empfohlen wird, diese Technik verantwortungsbewusst anzuwenden. Durch das Erstellen von Shrinkwrap-Dateien schreiben Sie bestimmte Versionen der Abhängigkeiten fest. Dies ist einerseits nützlich, um den stabilen Betrieb des Projekts sicherzustellen, andererseits kann es Benutzer daran hindern, kritische Patches zu installieren, was andernfalls automatisch erfolgen würde. Tatsächlich empfiehlt npm dringend, bei der Entwicklung von Bibliotheken keine Shrinkwrap-Dateien zu verwenden, um deren Verwendung auf CI-Systeme zu beschränken.
Suchen von Paket- und Abhängigkeitsinformationen
Leider ist es bei all den zahlreichen Informationen zum Abhängigkeitsmanagement in der npm-
Dokumentation manchmal schwierig, in diesen Informationen zu navigieren. Wenn Sie wissen möchten, was genau während der Installation von Abhängigkeiten installiert oder
--dry-run
wird, bevor Sie das Paket an npm senden, können Sie mit verschiedenen Befehlen das
--dry-run
verwenden. Die Verwendung dieses Flags führt dazu, dass das Team das System nicht beeinflusst. Beispielsweise
npm install --dry-run
Befehl
npm install --dry-run
die Abhängigkeiten nicht tatsächlich, und der Befehl
npm publish --dry-run
startet den Paketveröffentlichungsprozess nicht.
Hier sind einige ähnliche Befehle:
npm ci --dry-run # , package-lock.json npm-shrinkwrap.json npm pack --dry-run # , npm install <dep> --verbose --dry-run #
Zusammenfassung
Vieles, worüber wir hier gesprochen haben, hängt von den Besonderheiten der Ausführung verschiedener Operationen mit npm ab. Wir sprechen über das Verpacken, Veröffentlichen, Installieren von Paketen und das Arbeiten mit Abhängigkeiten. Und angesichts der Tatsache, dass sich npm ständig weiterentwickelt, können wir sagen, dass sich dies alles in Zukunft ändern kann. Darüber hinaus hängt die Möglichkeit der praktischen Anwendung der hier gegebenen Empfehlungen davon ab, wie der Paketentwickler das Problem der Verwendung unterschiedlicher Versionen von Abhängigkeiten in unterschiedlichen Umgebungen wahrnimmt.
Hoffentlich hat Ihnen dieses Material geholfen, besser zu verstehen, wie das npm-Abhängigkeits-Ökosystem funktioniert. Wenn Sie sich noch eingehender mit dieser Frage befassen möchten, können Sie
hier die Unterschiede zwischen den
npm install
npm ci
und
npm install
nachlesen.
Hier erfahren Sie, was genau in die
npm-shrinkwrap.json
package-lock.json
und
npm-shrinkwrap.json
.
Auf der npm-Dokumentationsseite können Sie herausfinden, welche Projektdateien in Paketen enthalten sind und welche nicht.
Liebe Leser! Verwenden Sie die Datei npm-shrinkwrap.json in Ihren Projekten?
