Diese Dokumentation beantwortet meine Frage sehr schlecht. Ich habe diese Erklärungen nicht verstanden. Kann jemand in einfacheren Worten sagen? Vielleicht mit Beispielen, wenn es schwierig ist, einfache Wörter zu wählen?
EDIT fügte außerdem peerDependencies
hinzu, das eng verwandt ist und Verwirrung stiften kann.
Zusammenfassung wichtiger Verhaltensunterschiede:
dependencies
sind auf beiden installiert:
npm install
aus einem Verzeichnis, das package.json
enthältnpm install $package
in einem anderen VerzeichnisdevDependencies
sind:
npm install
in einem Verzeichnis installiert, das package.json
enthält, sofern Sie nicht das --production
-Flag übergeben (go upvote Gayan Chariths answer ).npm install "$package"
in einem anderen Verzeichnis installiert, es sei denn, Sie geben die Option --dev
an.npm install
fehlt, wird eine Warnung ausgegeben, und Sie müssen die Abhängigkeit manuell lösen. Wenn die Abhängigkeit fehlt, wird beim Ausführen eine Fehlermeldung angezeigt (erwähnt durch @nextgentech ).Transitivität (erwähnt von Ben Hutchison ):
dependencies
werden durchgehend installiert: Wenn A B erfordert und B C benötigt, wird C installiert, andernfalls könnte B nicht funktionieren, und A würde auch nicht funktionieren.
devDependencies
wird nicht durchgehend installiert. Z.B. Wir müssen B nicht testen, um A zu testen, so dass die Testabhängigkeiten von B weggelassen werden können.
Verwandte Optionen, die hier nicht behandelt werden:
bundledDependencies
, das in der folgenden Frage diskutiert wird: Vorteile gebündelter Abhängigkeiten gegenüber normalen Abhängigkeiten in NPMoptionalDependencies
(erwähnt von Aidan Feldman )dependencies
sind erforderlich, um ausgeführt zu werden, devDependencies
, um z. B. Unit-Tests, CoffeeScript-JavaScript-Transpilierung, Minification, ... zu entwickeln.
Wenn Sie ein Paket entwickeln möchten, laden Sie es herunter (z. B. über git clone
), gehen Sie zum Stammverzeichnis, das package.json
enthält, und führen Sie Folgendes aus:
npm install
Da Sie über die eigentliche Quelle verfügen, ist es klar, dass Sie sie entwickeln möchten. Daher werden standardmäßig sowohl dependencies
(da Sie zum Entwickeln natürlich laufen müssen) als auch devDependency
-Abhängigkeiten installiert.
Wenn Sie jedoch nur ein Endbenutzer sind, der nur ein Paket zur Verwendung installieren möchte, können Sie dies von jedem beliebigen Verzeichnis aus tun:
npm install "$package"
In diesem Fall möchten Sie normalerweise keine Entwicklungsabhängigkeiten haben. Sie erhalten also nur das, was zur Verwendung des Pakets erforderlich ist: dependencies
.
Wenn Sie in diesem Fall wirklich Entwicklungspakete installieren möchten, können Sie die Konfigurationsoption dev
auf true
setzen, möglicherweise über die Befehlszeile:
npm install "$package" --dev
Die Option ist standardmäßig false
, da dies ein weitaus seltener ist.
(Vor 3.0 getestet)
Quelle: https://nodejs.org/de/blog/npm/peer-dependencies/
Bei regelmäßigen Abhängigkeiten können Sie mehrere Versionen der Abhängigkeit haben: Sie wird einfach im node_modules
der Abhängigkeit installiert.
Z.B. Wenn dependency1
und dependency2
in verschiedenen Versionen von dependency3
abhängen, sieht der Projektbaum folgendermaßen aus:
root/node_modules/
|
+- dependency1/node_modules/
| |
| +- dependency3 v1.0/
|
|
+- dependency2/node_modules/
|
+- dependency3 v2.0/
Plugins sind jedoch Pakete, die normalerweise kein anderes Paket benötigen, das in diesem Kontext Host genannt wird. Stattdessen:
Z.B. Wenn dependency1
und dependency2
peer von dependency3
abhängen, sieht der Projektbaum folgendermaßen aus:
root/node_modules/
|
+- dependency1/
|
+- dependency2/
|
+- dependency3 v1.0/
Dies geschieht auch, wenn Sie dependency3
in Ihrer package.json
-Datei nie erwähnen.
Ich denke, das ist ein Beispiel des Inversion of Control Design-Musters.
Ein prototypisches Beispiel für Peer-Abhängigkeiten ist Grunt, der Host und seine Plugins.
Auf einem Grunt-Plugin wie https://github.com/gruntjs/grunt-contrib-uglify sehen Sie beispielsweise Folgendes:
grunt
ist ein peer-dependency
require('grunt')
ist unter tests/
: es wird vom Programm nicht wirklich verwendet.Wenn der Benutzer ein Plugin verwendet, fordert er das Plugin implizit aus der Gruntfile
an, indem es eine grunt.loadNpmTasks('grunt-contrib-uglify')
-Zeile hinzufügt. Es ist jedoch grunt
, die der Benutzer direkt anruft.
Dies würde dann nicht funktionieren, wenn jedes Plugin eine andere Grunt-Version benötigt.
Ich denke, die Dokumentation beantwortet die Frage ziemlich gut, vielleicht kennen Sie sich mit Knoten/anderen Paketmanagern nicht genug aus. Ich verstehe es wahrscheinlich nur, weil ich etwas über Ruby Bundler weiß.
Die Schlüsselzeile lautet:
Diese Komponenten werden bei der Ausführung von npm link oder npm vom Stammverzeichnis eines Pakets aus installiert und können wie alle anderen npm-Konfigurationsparameter verwaltet werden. Weitere Informationen zum Thema finden Sie unter npm-config (7).
Und dann unter npm-config (7) dev
finden:
Default: false
Type: Boolean
Install dev-dependencies along with packages.
Wenn Sie devDependencies nicht installieren möchten, können Sie npm install --production
verwenden.
Mokka wäre zum Beispiel normalerweise eine devDependency, da das Testen in der Produktion nicht erforderlich ist, während express eine Abhängigkeit darstellt.
So speichern Sie ein Paket in package.json as dev-Abhängigkeiten:
npm install "$package" --save-dev
Wenn Sie npm install
ausführen, werden sowohl devDependencies
als auch dependencies
installiert. Um zu vermeiden, dass devDependencies
installiert wird, führen Sie Folgendes aus:
npm install --production
Abhängigkeiten
Abhängigkeiten, die Ihr Projekt ausführen muss, z. B. eine Bibliothek, die Funktionen enthält, die Sie mit Ihrem Code aufrufen.
Sie werden durchgehend installiert (wenn A von B abhängt, hängt von npm Install auf A B und C ab).
Beispiel: lodash: Ihr Projekt ruft einige lodash-Funktionen auf.
devDependencies
Abhängigkeiten, die Sie nur während der Entwicklung oder Veröffentlichung benötigen, wie Compiler, die Ihren Code in Javascript, Test-Frameworks oder Dokumentationsgeneratoren kompilieren.
Sie werden nicht durchgehend installiert (wenn A von B abhängt oder von C abhängt, installiert npm auf A nur B).
Beispiel: grunt: Ihr Projekt verwendet grunt, um sich selbst zu erstellen.
peerDependencies
Abhängigkeiten, die Ihr Projekt in das übergeordnete Projekt einbindet oder ändert, in der Regel ein Plug-In für eine andere Bibliothek oder ein anderes Tool. Es ist nur eine Überprüfung, um sicherzustellen, dass das übergeordnete Projekt (Projekt, das von Ihrem Projekt abhängt) von dem Projekt abhängig ist, in das Sie einbinden. Wenn Sie also ein Plugin C erstellen, das die Bibliothek B um Funktionalität erweitert, muss jemand, der ein Projekt A erstellt, eine Abhängigkeit von B haben, wenn er von C abhängig ist.
Sie werden nicht installiert (es sei denn, npm <3), sie werden nur geprüft.
Beispiel: grunt: Ihr Projekt fügt Grunt Funktionalität hinzu und kann nur für Projekte verwendet werden, die Grunt verwenden.
Diese Dokumentation erklärt Peer-Abhängigkeiten sehr gut: https://nodejs.org/de/blog/npm/peer-dependencies/
Die npm-Dokumentation wurde im Laufe der Zeit verbessert und bietet nun bessere Erklärungen zu den verschiedenen Arten von Abhängigkeiten: https://github.com/npm/cli/blob/latest/doc/files/package.json.md #devdependencies
Es gibt einige Module und Pakete, die nur für die Entwicklung erforderlich sind und nicht in der Produktion benötigt werden. Wie sagt es in der Dokumentation :
Wenn jemand plant, Ihr Modul herunterzuladen und in seinem Programm zu verwenden, möchte oder will es wahrscheinlich nicht das von Ihnen verwendete externe Test- oder Dokumentations-Framework herunterladen und erstellen. In diesem Fall sollten Sie diese zusätzlichen Elemente am besten in einem devDependencies-Hash auflisten.
Eine einfache Erklärung, die mir klarer wurde, ist:
Wenn Sie Ihre App bereitstellen, müssen Module in Abhängigkeiten installiert werden, ansonsten funktioniert Ihre App nicht. Module in devDependencies müssen nicht auf dem Produktionsserver installiert werden, da Sie nicht auf diesem Computer entwickeln . link
Ich möchte meine Antwort auf diese Abhängigkeiten erklären
dependencies
werden für die direkte Verwendung in Ihrer Codebase verwendet, Dinge, die normalerweise im Produktionscode enden, oder CodeabschnittedevDependencies
werden für den Build-Prozess verwendet, Tools, mit denen Sie den End-Code verwalten können, Testmodule von Drittanbietern (z. B. Webpack-Zeug).peerDependencies
ergab für mich keinen Sinn, bis ich diesen Ausschnitt aus einem Blogbeitrag zum oben genannten Thema Ciro las :
Was [ Plugins ] benötigen, ist eine Möglichkeit, diese „Abhängigkeiten“ zwischen Plugins und ihrem Host-Paket auszudrücken. Eine Art zu sagen: "Ich arbeite nur, wenn ich mit Version 1.2.x meines Host-Pakets verbunden bin. Wenn Sie mich also installieren, stellen Sie sicher, dass es sich neben einem kompatiblen Host befindet." Diese Beziehung wird als Peer-Abhängigkeit bezeichnet.
peerDependencies
sind für Plugins gedacht, Bibliotheken, für deren Ausführung eine "Host" -Bibliothek erforderlich ist, die jedoch möglicherweise zu einem Zeitpunkt geschrieben wurde bevor die neueste Version des Hosts veröffentlicht wurde.
Das heißt, wenn ich PluginX v1
Für HostLibraryX v3
Schreibe und weggehe, gibt es keine Garantie, dass PluginX v1
Funktioniert, wenn HostLibraryX v4
(Oder sogar HostLibraryX v3.0.1
) ) es ist veröffentlicht worden.
Aus der Sicht des Plugins ist es nur fügt Funktionen zur Host-Bibliothek hinzu. Ich brauche den Host nicht wirklich, um einem Plugin eine Abhängigkeit hinzuzufügen, und Plugins sind oft nicht buchstäblich abhängig von ihrem Host. Wenn Sie den Host nicht haben, führt das Plugin harmlos nichts aus.
Dies bedeutet, dass dependencies
nicht das richtige Konzept für Plugins ist.
Schlimmer noch, wenn mein Host wie eine Abhängigkeit behandelt würde, würden wir in dieser Situation enden, dass derselbe Blog-Beitrag erwähnt (ein wenig bearbeitet, um die Antwort zu verwenden, die aus Host & besteht. Plugin):
Wenn wir jedoch die aktuelle Version von HostLibraryX als Abhängigkeit für PluginX betrachten, führt das Ausführen von
npm install
Zu dem unerwarteten Abhängigkeitsdiagramm von├── [email protected] └─┬ [email protected] └── [email protected]
Ich überlasse die subtilen Fehler, die vom Plug-in mit einer anderen [HostLibraryX] -API als der Hauptanwendung ausgehen, Ihrer Vorstellungskraft.
... das ist der springende Punkt bei Plugins. Wenn der Host nun so nett wäre, Abhängigkeitsinformationen für alle seiner Plugins aufzunehmen, würde dies das Problem lösen, aber das würde auch ein riesiges neues kulturelles Problem einführen: Plugin-Verwaltung!
Der springende Punkt bei Plugins ist, dass sie anonym gepaart werden können. In einer perfekten Welt wäre es ordentlich, wenn der Host sie alle verwalten würde, aber wir werden keine Bibliotheken für Herdenkatzen benötigen.
Stattdessen haben wir das Konzept, Gleichaltrige zu sein. Weder Host noch Plugin befinden sich im Abhängigkeitsbereich des anderen. Beide leben auf der gleichen Ebene des Abhängigkeitsgraphen.
Wenn ich PluginX v1
Und erwarte ein Peer von (das heißt habe eine Peer-Abhängigkeit von) HostLibraryX v3
Bin, sage ich das auch . Wenn Sie automatisch auf den neuesten HostLibraryX v4
Aktualisiert haben (beachten Sie, dass dies die Version ist 4) UND haben Plugin v1
installiert, das müssen Sie wissen, oder?
npm
kann diese Situation für mich nicht bewältigen -
"Hey, ich sehe, dass Sie
PluginX v1
Verwenden! Ich stufeHostLibraryX
automatisch von v4 auf v3 herunter, kk?"
... oder...
"Hey, ich sehe, dass Sie
PluginX v1
Verwenden. Das erwartetHostLibraryX v3
, Das Sie während Ihres letzten Updates im Staub gelassen haben. Um sicherzugehen, deinstalliere ichPlugin v1
!! 1!
Wie wäre es mit nein, npm ?!
Npm also nicht. Es macht Sie auf die Situation aufmerksam und lässt Sie herausfinden, ob HostLibraryX v4
Ein geeigneter Partner für Plugin v1
Ist.
Gutes peerDependency
Management in Plugins lässt dieses Konzept in der Praxis intuitiver funktionieren. Aus dem Blogbeitrag nochmal ...
Ein Tipp: Peer-Abhängigkeitsanforderungen sollten im Gegensatz zu denen für reguläre Abhängigkeiten nachsichtig sein. Sie sollten Ihre Peer-Abhängigkeiten nicht auf bestimmte Patch-Versionen beschränken. Es wäre wirklich ärgerlich, wenn ein Chai-Plugin von Chai 1.4.1 abhängen würde, während ein anderes von Chai 1.5.0 abhängen würde, einfach weil die Autoren faul waren und nicht die Zeit damit verbrachten, die tatsächliche Mindestversion von Chai herauszufinden kompatibel mit.
Abhängigkeiten vs dev Abhängigkeiten
Dev-Abhängigkeiten sind Module, die nur während der Entwicklung benötigt werden, während Abhängigkeiten zur Laufzeit benötigt werden. Wenn Sie Ihre Anwendung bereitstellen, müssen Abhängigkeiten installiert werden, sonst funktioniert Ihre Anwendung einfach nicht. Bibliotheken, die Sie aus Ihrem Code aufrufen, der die Ausführung des Programms ermöglicht, können als Abhängigkeiten betrachtet werden.
zB- React, React - dom
Dev-Abhängigkeitsmodule müssen nicht auf dem Produktionsserver installiert werden, da Sie auf diesem Computer keine Compiler entwickeln werden. Compiler, die Ihren Code auf Javascript umwandeln, Test-Frameworks und Dokumentgeneratoren können als Dev-Abhängigkeiten betrachtet werden, da sie nur während der Entwicklung erforderlich sind.
ZB ESLint, Babel, Webpack
@FYI,
mod-a
dev-dependents:
- mod-b
dependents:
- mod-c
mod-d
dev-dependents:
- mod-e
dependents:
- mod-a
----
npm install mod-d
installed modules:
- mod-d
- mod-a
- mod-c
----
checkout the mod-d code repository
npm install
installed modules:
- mod-a
- mod-c
- mod-e
Wenn Sie in npm veröffentlichen, ist es wichtig, dass Sie das richtige Flag für die richtigen Module verwenden. Wenn Ihr npm-Modul funktionieren soll, verwenden Sie das Flag "--save", um das Modul als Abhängigkeit zu speichern. Wenn Ihr Modul nicht funktionieren muss, aber zum Testen benötigt wird, verwenden Sie das Flag "--save-dev".
# For dependent modules
npm install dependent-module --save
# For dev-dependent modules
npm install development-module --save-dev
Wenn Sie versuchen, ein npm-Paket zu verteilen, sollten Sie die Verwendung von dependencies
vermeiden. Stattdessen müssen Sie in Betracht ziehen, es in peerDependencies
hinzuzufügen oder aus dependencies
zu entfernen.
Zusamenfassend
Abhängigkeiten - npm install <package> save-prod
installierte Pakete, die von Ihrer Anwendung in der Produktionsumgebung benötigt werden.
DevDependencies - npm install <package> --save-dev
installiert Pakete, die nur für die lokale Entwicklung und das Testen erforderlich sind
npm install
werden alle in package.json genannten Pakete installiertwenn Sie also auf Ihrem lokalen Computer arbeiten, geben Sie einfach npm install
ein und fahren Sie fort :)