Diese Dokumentation beantwortet meine Frage nur unzureichend. Ich habe die Erklärungen nicht verstanden. Kann mir das jemand in einfacheren Worten erklären? Vielleicht mit Beispielen, wenn es schwer ist, einfache Worte zu wählen?
EDIT fügte auch peerDependencies
hinzu, was eng verwandt ist und Verwirrung stiften könnte.
Zusammenfassung der wichtigsten Verhaltensunterschiede:
Abhängigkeiten
werden bei beiden installiert:npm install
aus einem Verzeichnis, das package.json
enthältnpm install $package
in jedem anderen VerzeichnisdevDependencies
werden:npm install
in einem Verzeichnis, das package.json
enthält, es sei denn, Sie übergeben das --production
Flag (bewerten Sie Gayan Chariths Antwort).npm install "$package"
in einem anderen Verzeichnis installiert werden, es sei denn, Sie geben ihm die Option --dev
.peerDependencies
:npm install
fehlen, und Sie müssen die Abhängigkeit selbst manuell lösen. Wenn die Abhängigkeit fehlt, erhält man beim Ausführen eine Fehlermeldung (erwähnt von @nextgentech)dependencies
werden transitiv installiert: wenn A B benötigt, und B C benötigt, dann wird C installiert, ansonsten könnte B nicht funktionieren, und A auch nicht.devDependencies
wird nicht transitorisch installiert. Z.B. brauchen wir B nicht zu testen, um A zu testen, also können die Testabhängigkeiten von B weggelassen werden.
Verwandte Optionen, die hier nicht diskutiert werden:bundledDependencies
, die in der folgenden Frage diskutiert wird: https://stackoverflow.com/questions/11207638/advantages-of-bundleddependencies-over-normal-dependencies-in-npm?lq=1optionalDependencies
(erwähnt von Aidan Feldman)dependencies
werden zum Ausführen benötigt, devDependencies
nur zum Entwickeln, z.B.: Unit-Tests, CoffeeScript zu JavaScript Transpilierung, Minifizierung, ...
Wenn Sie ein Paket entwickeln wollen, laden Sie es herunter (z.B. über git clone
), gehen Sie zu seinem Stammverzeichnis, das package.json
enthält, und führen Sie aus:
npm install
Da Sie den eigentlichen Quellcode haben, ist es klar, dass Sie es entwickeln wollen, also werden standardmäßig sowohl die dependencies
(da Sie es natürlich zum Entwickeln ausführen müssen) als auch die devDependency
-Abhängigkeiten installiert.
Wenn Sie jedoch nur ein Endbenutzer sind, der ein Paket installieren möchte, um es zu benutzen, können Sie dies von jedem Verzeichnis aus tun:
npm install "$package"
In diesem Fall wollen Sie normalerweise nicht die Entwicklungsabhängigkeiten, so dass Sie nur das bekommen, was benötigt wird, um das Paket zu benutzen: dependencies
.
Wenn Sie in diesem Fall wirklich Entwicklungspakete installieren wollen, können Sie die Konfigurationsoption dev
auf true
setzen, möglicherweise von der Kommandozeile aus wie folgt:
npm install "$package" --dev
Die Option ist standardmäßig auf false
gesetzt, da dies ein viel seltenerer Fall ist.
(Getestet vor 3.0)
Quelle: https://nodejs.org/en/blog/npm/peer-dependencies/
Mit regulären Abhängigkeiten können Sie mehrere Versionen der Abhängigkeit haben: Sie werden einfach innerhalb der node_modules
der Abhängigkeit installiert.
Wenn z.B. dependency1
und dependency2
beide von dependency3
in verschiedenen Versionen abhängen, sieht der Projektbaum wie folgt aus:
root/node_modules/
|
+- dependency1/node_modules/
| |
| +- dependency3 v1.0/
|
|
+- dependency2/node_modules/
|
+- dependency3 v2.0/
Plugins sind jedoch Pakete, die normalerweise das andere Paket, das in diesem Zusammenhang Host genannt wird, nicht benötigen. Stattdessen:
dependency1
und dependency2
von dependency3
abhängen, wird der Projektbaum wie folgt aussehen:root/node_modules/
|
+- dependency1/
|
+- dependency2/
|
+- dependency3 v1.0/
Das passiert, obwohl Sie dependency3
nie in Ihrer package.json
Datei erwähnen.
Ich denke, dies ist ein Beispiel für das Inversion of Control Entwurfsmuster.
Ein prototypisches Beispiel für Peer-Abhängigkeiten ist Grunt, der Host, und seine Plugins.
Bei einem Grunt-Plugin wie https://github.com/gruntjs/grunt-contrib-uglify werden Sie zum Beispiel sehen, dass:
grunt
ist eine Peer-Abhängigkeit
require('grunt')
befindet sich unter tests/
: es wird nicht wirklich vom Programm benutzt.
Wenn der Benutzer dann ein Plugin benutzt, wird er implizit das Plugin aus der Gruntfile
anfordern, indem er eine grunt.loadNpmTasks('grunt-contrib-uglify')
Zeile hinzufügt, aber es ist grunt
, das der Benutzer direkt aufruft.
Dies würde dann nicht funktionieren, wenn jedes Plugin eine andere Grunt-Version benötigt.Ich denke, die Dokumentation beantwortet die Frage recht gut, vielleicht bist du einfach nicht vertraut genug mit node / anderen Paketmanagern. Ich verstehe es wahrscheinlich nur, weil ich mich ein wenig mit Ruby Bundler auskenne. Die Schlüsselzeile ist:
Diese Dinge werden installiert, wenn man npm link oder npm install aus dem Wurzelverzeichnis eines Pakets ausführt und können wie jeder andere npm-Konfigurationsparameter verwaltet werden. Siehe npm-config(7) für weitere Informationen zu diesem Thema. Und dann finden Sie unter npm-config(7)
dev
:
Default: false
Type: Boolean
Install dev-dependencies along with packages.
Es gibt einige Module und Pakete, die nur für die Entwicklung notwendig sind, die aber in der Produktion nicht benötigt werden. Wie es in der Dokumentation steht:
Wenn jemand plant, Ihr Modul herunterzuladen und in seinem Programm zu verwenden, dann will oder muss er wahrscheinlich nicht das externe Test- oder Dokumentations-Framework, das Sie verwenden, herunterladen und bauen. In diesem Fall ist es am besten, diese zusätzlichen Elemente in einem devDependencies-Hash aufzulisten.