Quelle est la différence entre les dépendances, devDependencies et peerDependencies dans le fichier npm package.json?

2030

Cette documentation répond très mal à ma question. Je n'ai pas compris ces explications. Quelqu'un peut-il dire en termes plus simples? Peut-être avec des exemples s'il est difficile de choisir des mots simples?

EDIT a également ajouté peerDependencies, qui est étroitement lié et pourrait prêter à confusion.

Vitalii Korsakov
la source
48
Notez qu'il y en a aussi optionalDependenciesmaintenant.
Aidan Feldman
118
@AidanFeldman "optionalDependencies" est mon oxymore du jour
Nick Bull
1
La documentation de npm indique: "dépendances": packages requis par votre application en production. "devDependencies": packages qui ne sont nécessaires que pour le développement local et les tests. voir le lien: docs.npmjs.com/…
Deke

Réponses:

2367

Résumé des différences de comportement importantes:

  • dependencies sont installés sur les deux:

    • npm install à partir d'un répertoire qui contient package.json
    • npm install $package sur tout autre répertoire
  • devDependencies sont:

    • également installé sur npm installun répertoire qui contient package.json, à moins que vous ne passiez le --productiondrapeau (allez voter la réponse de Gayan Charith ).
    • n'est installé sur npm install "$package"aucun autre répertoire, sauf si vous lui en donnez l' --devoption.
    • ne sont pas installés de manière transitoire.
  • peerDependencies:

    • avant 3.0: sont toujours installés s'ils sont manquants et génèrent une erreur si plusieurs versions incompatibles de la dépendance sont utilisées par différentes dépendances.
    • devrait démarrer sur 3.0 (non testé): donnez un avertissement s'il manque npm install, et vous devez résoudre la dépendance vous-même manuellement. Lors de l'exécution, si la dépendance est manquante, vous obtenez une erreur (mentionnée par @nextgentech )
  • Transitivité (mentionnée par Ben Hutchison ):

    • dependencies sont installés de manière transitoire: si A nécessite B et B nécessite C, alors C est installé, sinon B ne pourrait pas fonctionner et A. non plus.

    • devDependenciesn'est pas installé de manière transitoire. Par exemple, nous n'avons pas besoin de tester B pour tester A, donc les dépendances de test de B peuvent être laissées de côté.

Options connexes non discutées ici:

devDependencies

dependenciessont nécessaires pour exécuter, devDependenciesuniquement pour développer, par exemple: tests unitaires, transpilation CoffeeScript vers JavaScript, minification, ...

Si vous allez développer un paquet, vous le téléchargez (par exemple via git clone), allez à sa racine qui contient package.jsonet exécutez:

npm install

Puisque vous avez la source réelle, il est clair que vous souhaitez la développer, donc par défaut, à la fois dependencies(puisque vous devez, bien sûr, exécuter pour développer) et les devDependencydépendances sont également installés.

Si toutefois vous n'êtes qu'un utilisateur final qui souhaite simplement installer un package pour l'utiliser, vous le ferez à partir de n'importe quel répertoire:

npm install "$package"

Dans ce cas, vous ne voulez pas normalement les dépendances de développement, de sorte que vous obtenez juste ce qu'il faut pour utiliser le package: dependencies.

Si vous voulez vraiment installer des packages de développement dans ce cas, vous pouvez définir l' devoption de configuration sur true, éventuellement à partir de la ligne de commande comme:

npm install "$package" --dev

L'option est falsepar défaut car il s'agit d'un cas beaucoup moins courant.

peerDependencies

(Testé avant 3.0)

Source: https://nodejs.org/en/blog/npm/peer-dependencies/

Avec les dépendances régulières, vous pouvez avoir plusieurs versions de la dépendance: elle est simplement installée à l'intérieur node_modulesde la dépendance.

Par exemple, si dependency1et les dependency2deux dépendent de dependency3versions différentes, l'arborescence du projet ressemblera à:

root/node_modules/
                 |
                 +- dependency1/node_modules/
                 |                          |
                 |                          +- dependency3 v1.0/
                 |
                 |
                 +- dependency2/node_modules/
                                            |
                                            +- dependency3 v2.0/

Les plugins, cependant, sont des packages qui ne nécessitent normalement pas l'autre package, qui est appelé l' hôte dans ce contexte. Au lieu:

  • les plugins sont requis par l'hôte
  • les plugins offrent une interface standard que l'hôte s'attend à trouver
  • seul l'hôte sera appelé directement par l'utilisateur, il doit donc y en avoir une seule version.

Par exemple, si dependency1et les dependency2pairs en dépendent dependency3, l'arborescence du projet ressemblera à:

root/node_modules/
                 |
                 +- dependency1/
                 |
                 +- dependency2/
                 |
                 +- dependency3 v1.0/

Cela se produit même si vous ne le mentionnez jamais dependency3dans votre package.jsonfichier.

Je pense que ceci est une instance du modèle de conception d' inversion de contrôle .

Un exemple prototype de dépendances entre pairs est Grunt, l'hôte et ses plugins.

Par exemple, sur un plugin Grunt comme https://github.com/gruntjs/grunt-contrib-uglify , vous verrez que:

  • grunt est un peer-dependency
  • le seul require('grunt')est sous tests/: il n'est pas réellement utilisé par le programme.

Ensuite, lorsque l'utilisateur utilisera un plugin, il aura implicitement besoin du plugin depuis Gruntfileen ajoutant une grunt.loadNpmTasks('grunt-contrib-uglify')ligne, mais c'est gruntque l'utilisateur appellera directement.

Cela ne fonctionnerait pas si chaque plugin nécessitait une version Grunt différente.

Manuel

Je pense que la documentation répond assez bien à la question, peut-être que vous n'êtes pas assez familier avec les gestionnaires de nœuds / autres packages. Je ne le comprends probablement que parce que je connais un peu le bundle Ruby.

La ligne clé est:

Ces éléments seront installés lors de la liaison npm ou de l'installation npm à partir de la racine d'un package et peuvent être gérés comme n'importe quel autre paramètre de configuration npm. Voir npm-config (7) pour plus d'informations sur le sujet.

Et puis sous npm-config (7) trouver dev:

Default: false
Type: Boolean

Install dev-dependencies along with packages.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
la source
5
Ah. Je vois que j'ai mal compris. Votre réponse se lit comme si npm install packagec'était une commande que vous utiliseriez pour installer tous les packages qui ne sont pas des dépendances de dev, plutôt que ce que je pense maintenant que vous vouliez dire, qui était «installez le package appelé [package]», et c'est ainsi que je pensais que cela fonctionnait avant de lire ceci. Si j'étais vous, je modifierais pour dire [nom-package] qui montre clairement que ce que vous voulez dire est «insérer-nom-ici».
Tom W
184
C'est bien! Je ne m'en suis jamais rendu compte, mais cette réponse m'a appris que la différence entre les dépendances et les devDependencies n'est applicable que si vous allez publier un package npm. Si vous travaillez uniquement sur une application ou un site, cela ne devrait pas trop d'importance. Merci!
jedd.ahyoung
3
Ce message devrait être mis à jour pour refléter le changement de peerDependenciescomportement dans le prochain npm @ 3. De blog.npmjs.org/post/110924823920/npm-weekly-5 : "Nous ne téléchargerons plus automatiquement la dépendance des pairs. Au lieu de cela, nous vous avertirons si la dépendance des pairs n'est pas déjà installée. Cela vous oblige pour résoudre les conflits peerDependency vous-même, manuellement, mais à long terme, cela devrait rendre moins probable que vous vous retrouviez dans une situation délicate avec les dépendances de vos packages. "
nextgentech
8
En outre, devDependencies ne sont pas installés de manière transitoire par les packages dépendants. Exemple: le package A dépend du package B. Le package B dépend du package C, et B dépend également du package D. Si vous exécutez à npm installpartir du package A, vous obtiendrez B et C mais pas D.
Ben Hutchison
9
Il est important de devDependenciesnoter que ceux qui ne sont pas installés lorsque NODE_ENVest défini sur production.
Augusto Franzoia
491

Si vous ne souhaitez pas installer devDependencies, vous pouvez utiliser npm install --production

Gayan Charith
la source
1
npm install --save est pour la dépendance logicielle?
Vamsi Pavan Mahesh,
19
npm install installera toutes les dépendances. L'indicateur --save est utilisé lorsque vous souhaitez également ajouter le module spécifique à package.json. ex: - npm install uglify --save installera uglify dans votre dossier de projet et ajoutera uglify au projet, fichier package.json.
Gayan Charith
6
Et comme nous parlons de devDependencies, vous pouvez utiliser --save-dev pour enregistrer le nouveau module en tant que devDependency. Exemple: npm install uglify --save-dev
Mykaelos
9
Depuis npm 5, l' --saveoption n'est plus nécessaire. Si vous faites "npm install my-package", il ajoutera my-package en tant que dépendance dans votre package.jsonfichier.
Martin Carel
installation juste npm
sultan aslam
116

Par exemple, mocha serait normalement une devDependency, car les tests ne sont pas nécessaires en production, tandis qu'express serait une dépendance.

Dan Kohn
la source
4
Je pencherais pour mettre le test en tant que dépendance, car vous voudrez peut-être exécuter des auto-tests avant de lancer le serveur de production
47
Je recommanderais plutôt d'utiliser un service d'intégration continue comme Hudson ou CircleCI qui exécute vos tests et se déploie ensuite en production s'ils réussissent.
Dan Kohn
1
Il peut toujours être pertinent de tester le serveur réel parce que le serveur CI peut différer d'une manière ou d'une autre du serveur prod, et cette différence peut par exemple empêcher l'application de démarrer ...
Nicole
2
@Nicole pourquoi voudriez-vous que votre serveur de transfert ne soit pas identique en configuration à votre prod?
Lucas
1
Là encore, l'ajout de dépendances de test en tant que dépendances régulières introduit un tas de bibliothèques supplémentaires, chacune pouvant échouer d'une manière ou d'une autre. Je pencherais (jeu de mots!) Vers des serveurs de production légers avec le moins de code possible. N'oubliez pas, le meilleur code n'est pas un code!
Stijn de Witt
69

dépendances
Dépendances que votre projet doit exécuter, comme une bibliothèque qui fournit des fonctions que vous appelez à partir de votre code.
Ils sont installés de manière transitoire (si A dépend de B dépend de C, npm install sur A installera B et C).
Exemple: lodash: votre projet appelle des fonctions lodash.

devDependencies
Dépendances dont vous n'avez besoin que pendant le développement ou la publication, comme les compilateurs qui prennent votre code et le compilent en javascript, testent des frameworks ou des générateurs de documentation.
Ils ne sont pas installés de manière transitoire (si A dépend de B dev-dépend de C, npm install sur A installera B uniquement).
Exemple: grunt: votre projet utilise grunt pour se construire.

peerDependencies
Dépendances auxquelles votre projet se connecte ou modifie dans le projet parent, généralement un plugin pour une autre bibliothèque ou un autre outil. Il s'agit simplement d'une vérification, en vous assurant que le projet parent (projet qui dépendra de votre projet) a une dépendance sur le projet auquel vous vous connectez. Donc, si vous créez un plugin C qui ajoute des fonctionnalités à la bibliothèque B, alors quelqu'un qui crée un projet A devra avoir une dépendance sur B s'il a une dépendance sur C.
Ils ne sont pas installés (sauf si npm <3), ils ne sont que vérifié.
Exemple: grunt: votre projet ajoute des fonctionnalités à grunt et ne peut être utilisé que sur des projets utilisant grunt.

Cette documentation explique très bien les dépendances entre pairs: https://nodejs.org/en/blog/npm/peer-dependencies/

De plus, la documentation npm a été améliorée au fil du temps et propose désormais de meilleures explications des différents types de dépendances: https://github.com/npm/cli/blob/latest/doc/files/package.json.md#devdependencies

qwertzguy
la source
63

Pour enregistrer un package dans package.json en tant que dépendances de développement:

npm install "$package" --save-dev

Lorsque vous l'exécutez, npm installil installera à la fois devDependencieset dependencies. Pour éviter l'installation, devDependenciesexécutez:

npm install --production
Mohammed Safeer
la source
3
vous pouvez également utiliser: npm i -S
Maysara Alhindi
36

Certains modules et packages sont uniquement nécessaires au développement, mais ne sont pas nécessaires en production. Comme il le dit dans la documentation :

Si quelqu'un envisage de télécharger et d'utiliser votre module dans son programme, il ne veut probablement pas ou n'a pas besoin de télécharger et de créer le cadre de test ou de documentation externe que vous utilisez. Dans ce cas, il est préférable de répertorier ces éléments supplémentaires dans un hachage devDependencies.

Amberlamps
la source
Que faire si vous exécutez uniquement le fichier bundle.js en production? avez-vous vraiment besoin de ces dépendances?
RegarBoy
Si vous exécutez bundle.js sur le serveur, vous faites un webpack côté serveur ou quelque chose ... Veuillez vérifier si c'est le cas car ce n'est généralement pas le cas et cela prend en fait beaucoup de travail pour que cela fonctionne correctement (je sais parce que je l'ai fait). Je soupçonne que votre bundle.js est simplement servi aux navigateurs et contient le code côté client.
Stijn de Witt
16

Une explication simple qui m'a rendu plus clair est:

Lorsque vous déployez votre application, les modules dans les dépendances doivent être installés ou votre application ne fonctionnera pas. Les modules dans devDependencies n'ont pas besoin d'être installés sur le serveur de production car vous ne développez pas sur cette machine. lien

Jyoti Duhan
la source
2
Donc, si nous faisons un site Web et dans la version prod vendor.js, toutes les bibliothèques seront intégrées, tous nos dépôts devraient être des dépôts si le code compilé est validé dans le dépôt. Et cela devrait être validé, car il est également étrange que vous deviez compiler le module, pas seulement l'installer (et les tests sont également quelque part ici car tout changement dans les sous-modules peut conduire à une régression) ...
Qwertiy
Super réponse, mais il y a une question? Est-ce que Webpack peut créer un bundle corrompu? Je suppose que les packages devDependencies ne fonctionneront pas dans la version du produit, webpack -pje veux dire. s'il vous plait répondez à ma question.
AmerllicA
S'il y a un problème lors de la génération de la production, votre processus de déploiement doit être conçu de manière à afficher une erreur au moment de la génération et à ne pas pousser le code corrompu en production (par exemple, vous pouvez essayer Jenkins). Les dépendances ne doivent de toute façon pas être installées sur le serveur de production.
Jyoti Duhan
et qu'en est-il des dépendances entre pairs?
dev27
13

Je voudrais ajouter à la réponse mon point de vue sur ces explications des dépendances

  • dependencies sont utilisés pour une utilisation directe dans votre base de code, des éléments qui se retrouvent généralement dans le code de production ou des morceaux de code
  • devDependencies sont utilisés pour le processus de construction, des outils qui vous aident à gérer la façon dont le code final se terminera, des modules de test tiers, (par exemple, des trucs webpack)
Sîrbu Nicolae-Cezar
la source
Qu'en est-il des actifs CSS?
Brian Zelip
8

En bref

  1. Dépendances - npm install <package> --save-prodinstalle les packages requis par votre application dans l'environnement de production.

  2. DevDependencies - npm install <package> --save-devinstalle les packages requis uniquement pour le développement local et les tests

  3. Une simple frappe npm installinstalle tous les packages mentionnés dans le package.json

donc si vous travaillez sur votre ordinateur local, tapez npm installet continuez :)

cherankrish
la source
6

peerDependenciesn'a pas vraiment de sens pour moi jusqu'à ce que je lise cet extrait d' un article de blog sur le sujet Ciro mentionné ci-dessus :

Ce dont les [ plugins ] ont besoin, c'est d'un moyen d'exprimer ces «dépendances» entre les plugins et leur package hôte. Une façon de dire: «Je ne travaille que lorsque je suis connecté à la version 1.2.x de mon package hôte, donc si vous m'installez, assurez-vous qu'il se trouve à côté d'un hôte compatible.» Nous appelons cette relation une dépendance entre pairs.

Le plugin attend une version spécifique de l'hôte ...

peerDependenciessont pour les plugins, les bibliothèques qui nécessitent une bibliothèque "hôte" pour remplir leur fonction, mais qui peuvent avoir été écrites à un moment avant la sortie de la dernière version de l'hôte.

Autrement dit, si j'écris PluginX v1pour HostLibraryX v3et m'en vais , il n'y a aucune garantie que PluginX v1cela fonctionnera quand HostLibraryX v4(ou même HostLibraryX v3.0.1) sera libéré.

... mais le plugin ne dépend pas de l'hôte ...

Du point de vue du plugin, il ajoute uniquement des fonctions à la bibliothèque hôte. Je n'ai pas vraiment "besoin" de l'hôte pour ajouter une dépendance à un plugin, et les plugins ne dépendent souvent pas littéralement de leur hôte. Si vous n'avez pas l'hôte, le plugin ne fait rien sans danger.

Cela signifie que ce dependenciesn'est pas vraiment le bon concept pour les plugins.

Pire encore, si mon hôte était traité comme une dépendance, nous finirions dans cette situation que le même article de blog mentionne (un peu modifié pour utiliser l'hôte et le plug-in composés de cette réponse):

Mais maintenant, [si nous traitons la version contemporaine de HostLibraryX comme une dépendance pour PluginX,] l'exécution npm installentraîne le graphique de dépendance inattendu de

├── HostLibraryX@4.0.0
└─┬ PluginX@1.0.0
  └── HostLibraryX@3.0.0

Je laisse à votre imagination les subtils échecs qui proviennent du plugin en utilisant une API [HostLibraryX] différente de l'application principale.

... et l'hôte ne dépend évidemment pas du plugin ...

... c'est tout l'intérêt des plugins. Maintenant, si l'hôte était assez gentil pour inclure des informations de dépendance pour tous ses plugins, cela résoudrait le problème, mais cela introduirait également un énorme nouveau problème culturel : la gestion des plugins!

L'intérêt des plugins est qu'ils peuvent se coupler de manière anonyme. Dans un monde parfait, la gestion de l'hôte par tous serait soignée et ordonnée, mais nous n'allons pas exiger des bibliothèques de chats de troupeau.

Si nous ne sommes pas dépendants hiérarchiquement, nous sommes peut-être des pairs indépendants l'un de l'autre ...

Au lieu de cela, nous avons le concept d'être des pairs. Ni l'hôte ni le plugin ne se trouvent dans le compartiment de dépendance de l'autre. Les deux vivent au même niveau du graphique de dépendance.


... mais ce n'est pas une relation automatisable. <<< Moneyball !!!

Si je suis PluginX v1et m'attends à un pair de (c'est-à-dire, avoir une dépendance de pair de ) HostLibraryX v3, je le dirai. Si vous avez mis à niveau automatiquement la dernière version HostLibraryX v4(notez qu'il s'agit de la version 4 ) ET que vous l' avez Plugin v1installé, vous devez savoir, non?

npm ne peut pas gérer cette situation pour moi -

"Hé, je vois que tu l'utilises PluginX v1! Je passe automatiquement HostLibraryXde la v4 à la v3, kk?"

... ou...

"Hé, je vois que vous utilisez PluginX v1. Cela attend HostLibraryX v3, que vous avez laissé dans la poussière lors de votre dernière mise à jour. Pour être sûr, je désinstalle automatiquement Plugin v1!! 1!

Et non, npm?!

Donc, npm ne le fait pas. Il vous avertit de la situation et vous permet de déterminer s'il HostLibraryX v4s'agit d'un pair approprié Plugin v1.


Coda

Une bonne peerDependencygestion des plugins rendra ce concept plus intuitif dans la pratique. Du blog , encore une fois ...

Un conseil: les exigences de dépendance des pairs, contrairement à celles des dépendances régulières, doivent être indulgentes. Vous ne devez pas verrouiller vos dépendances entre pairs vers des versions de correctifs spécifiques. Ce serait vraiment ennuyeux si un plugin Chai dépendait de Chai 1.4.1, tandis qu'un autre dépendait de Chai 1.5.0, simplement parce que les auteurs étaient paresseux et ne passaient pas le temps à déterminer la version minimale réelle de Chai. compatible avec.

ruffin
la source
4

Dépendances vs dépendances dev

Les dépendances de développement sont des modules qui ne sont nécessaires que pendant le développement tandis que les dépendances sont requises au moment de l'exécution. Si vous déployez votre application, des dépendances doivent être installées, sinon votre application ne fonctionnera tout simplement pas. Les bibliothèques que vous appelez à partir de votre code qui permet au programme de s'exécuter peuvent être considérées comme des dépendances.

Eg- React, React - dom

Les modules de dépendance de développement n'ont pas besoin d'être installés sur le serveur de production car vous n'allez pas développer sur cette machine. Les compilateurs qui convertissent votre code en javascript, les frameworks de test et les générateurs de documents peuvent être considérés comme des dépendances de développement car ils ne sont requis que pendant le développement.

Par exemple: 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

Si vous publiez vers npm, il est important que vous utilisiez l'indicateur correct pour les modules corrects. Si c'est quelque chose dont votre module npm a besoin pour fonctionner, utilisez l'indicateur "--save" pour enregistrer le module en tant que dépendance. Si c'est quelque chose que votre module n'a pas besoin de fonctionner mais qu'il est nécessaire pour les tests, alors utilisez l'indicateur "--save-dev".

# For dependent modules
npm install dependent-module --save

# For dev-dependent modules
npm install development-module --save-dev
Selva Ganapathi
la source
1

Lorsque vous essayez de distribuer un package npm, vous devez éviter de l'utiliser dependencies. Au lieu de cela, vous devez envisager de l'ajouter peerDependenciesou de le supprimer dependencies.

Melchia
la source
1

J'ai trouvé une explication simple.

Réponse courte:

dépendances "... sont celles dont votre projet a vraiment besoin pour pouvoir travailler en production."

devDependencies "... sont celles dont vous avez besoin pendant le développement."

peerDependencies "si vous souhaitez créer et publier votre propre bibliothèque afin qu'elle puisse être utilisée comme dépendance"

Plus de détails dans cet article: https://code-trotter.com/web/dependencies-vs-devdependencies-vs-peerdependencies

user-needs-help
la source