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

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

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

    • dependencies sont installées sur les deux:

      • npm install partir d’un répertoire contenant package.json
      • npm install $package sur tout autre répertoire
    • devDependencies sont:

      • Également installé sur npm install sur un répertoire contenant package.json , à moins que vous ne passiez le drapeau --production ( remplacez la réponse de Gayan Charith ).
      • pas installé sur npm install "$package" sur un autre répertoire, sauf si vous lui donnez l’option --dev .
      • ne sont pas installés de manière transitoire.
    • peerDependencies :

      • avant 3.0: sont toujours installés si elles sont manquantes et provoquent une erreur si plusieurs versions incompatibles de la dépendance sont utilisées par différentes dépendances.
      • attendu à partir de la version 3.0 (non testé): donnez un avertissement en cas d’absence lors de l’ npm install , et vous devrez résoudre la dépendance manuellement. Lors de l’exécution, si la dépendance est manquante, vous obtenez une erreur (mentionnée par @nextgentech )
    • Transitivité (mentionné par Ben Hutchison ):

      • dependencies sont installées de manière transitoire: si A requirejs B et B requirejs C, alors C est installé, sinon B ne pourrait pas fonctionner, et A.

      • devDependencies ne sont pas installées 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 ignorées.

    Options connexes non discutées ici:

    • bundledDependencies qui est discuté sur la question suivante: Avantages des bundledDependencies sur les dépendances normales dans NPM
    • optionalDependencies (mentionnées par Aidan Feldman )

    devDependencies

    dependencies sont nécessaires pour exécuter, devDependencies à développer, par exemple: tests unitaires, transpilation Coffeescript en Javascript, minification, …

    Si vous envisagez de développer un package, vous le téléchargez (par exemple via git clone ), allez à sa racine qui contient package.json , et lancez:

     npm install 

    Étant donné que vous avez la source réelle, il est clair que vous voulez la développer, par conséquent, par défaut, les deux dependencies (puisque vous devez bien sûr vous développer) et les dépendances devDependency sont également installées.

    Si toutefois vous n’êtes qu’un utilisateur final qui veut simplement installer un paquet pour l’utiliser, vous le ferez depuis n’importe quel répertoire:

     npm install "$package" 

    Dans ce cas, vous ne voulez normalement pas les dépendances de développement, vous obtenez donc ce qui est nécessaire pour utiliser le package: dependencies .

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

     npm install "$package" --dev 

    L’option est false par défaut car c’est un cas beaucoup moins courant.

    peerDependencies

    (testé avant 3.0)

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

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

    Par exemple, si dependency1 et dependency2 dépendent tous deux de la dependency3 à différentes versions, l’arborescence du projet ressemblera à:

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

    Les plugins sont cependant des paquets qui normalement ne requièrent pas l’autre paquetage, appelé l’ hôte dans ce contexte. Au lieu:

    • les plugins sont requirejs 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 en contenir une seule version.

    Par exemple, si dependency1 et dependency2 peer dépendent de la dependency3 , l’arborescence du projet ressemblera à ceci:

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

    Cela se produit même si vous ne mentionnez jamais la dependency3 dans votre fichier package.json .

    Je pense que c’est une instance du modèle de conception Inversion of Control .

    Un exemple prototypique de dépendances par les pairs est Grunt, l’hôte et ses plugins.

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

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

    Ensuite, lorsque l’utilisateur utilisera un plug-in, il exigera implicitement le plug-in de Gruntfile en ajoutant une ligne grunt.loadNpmTasks('grunt-consortingb-uglify') , mais il est grunt que l’utilisateur appelle directement.

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

    Manuel

    Je pense que le document répond assez bien à la question, peut-être que vous n’êtes pas seulement familiarisé avec les gestionnaires de paquets / autres. Je ne le comprends probablement que parce que je connais un peu le bundle Ruby.

    La ligne clé est la suivante:

    Ces éléments seront installés lors de l’installation de npm link ou npm install à partir de la racine d’un package et pourront ê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) trouvez dev :

     Default: false Type: Boolean Install dev-dependencies along with packages. 

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

    Par exemple, mocha serait normalement une devDependency, puisque le test n’est pas nécessaire en production, alors que express serait une dépendance.

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

     npm install "$package" --save-dev 

    Lorsque vous exécutez npm install il installe les dependencies et les dependencies . Pour éviter l’installation de devDependencies exécutez:

     npm install --production 

    Certains modules et packages ne sont nécessaires que pour le développement, ce qui n’est pas nécessaire en production. Comme il le dit dans la documentation :

    Si quelqu’un prévoit 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 construire le framework 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.

    dépendances
    Des 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, C, Npm install sur A installera B et C).
    Exemple: lodash: votre projet appelle des fonctions lodash.

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

    peerDependencies
    Les dépendances auxquelles votre projet accède ou modifie dans le projet parent, généralement un plug-in pour une autre bibliothèque ou un autre outil. Il s’agit simplement d’une vérification, en s’assurant que le projet parent (projet qui dépendra de votre projet) dépend du projet auquel vous êtes connecté. Donc, si vous créez un plug-in C qui ajoute des fonctionnalités à la bibliothèque B, alors une personne qui crée un projet A devra avoir une dépendance de B si elle dépend de C.
    Ils ne sont pas installés (sauf si npm <3), ils sont uniquement vérifiés.
    Exemple: grunt: votre projet ajoute de la fonctionnalité à la grogne et ne peut être utilisé que sur des projets qui utilisent le grunt.

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

    En outre, la documentation npm a été améliorée au fil du temps et contient désormais de meilleures explications sur les différents types de dépendances: https://github.com/npm/npm/blob/master/doc/files/package.json.md#devdependencies

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

    Lorsque vous déployez votre application, les modules dépendants 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

    Je voudrais append à la réponse mon avis sur ces explications de dépendances

    • dependencies sont utilisées pour une utilisation directe dans votre base de code, des choses qui se retrouvent généralement dans le code de production ou des morceaux de code
    • devDependencies sont utilisées pour le processus de construction, des outils qui vous aident à gérer la manière dont le code de fin se terminera, des modules de test tiers (par exemple, des éléments de webpack)

    Lorsque vous essayez de dissortingbuer un package npm, vous devez éviter d’utiliser des dependencies . Au lieu de cela, vous devez envisager de l’append à peerDependencies ou de le supprimer des dependencies .

    peerDependencies n’avait pas vraiment de sens pour moi jusqu’à ce que je lise cet extrait d’ un article de blog sur le sujet mentionné ci-dessus :

    Ce dont [ plugins ] a besoin, c’est d’une manière d’exprimer ces «dépendances» entre les plugins et leur paquet hôte. Une manière de dire: «Je ne travaille que lorsque branché à la version 1.2.x de mon paquet 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 par les pairs.

    Le plug-in attend une version spécifique de l’hôte …

    peerDependencies concerne les plugins, les bibliothèques qui nécessitent une bibliothèque “hôte” pour exécuter leur fonction, mais qui peuvent avoir été écrites à la fois avant la publication de la dernière version de l’hôte.

    En d’autres PluginX v1 , si j’écris PluginX v1 pour HostLibraryX v3 et que je PluginX v1 HostLibraryX v3 , il n’y a aucune garantie que PluginX v1 fonctionne lorsque HostLibraryX v4 (ou même HostLibraryX v3.0.1 ) est disponible.

    … mais le plugin ne dépend pas de l’hôte …

    Du sharepoint vue du plug-in, il ajoute uniquement des fonctions à la bibliothèque hôte. Je n’ai pas vraiment besoin de l’hôte et les plugins ne dépendent pas littéralement de leur hôte. Si vous n’avez pas l’hôte, le plug-in ne fait rien.

    Cela signifie que les dependencies ne sont pas vraiment le bon concept pour les plugins.

    Pire encore, si mon hôte était traité comme une dépendance, nous nous retrouverions dans cette situation que le même article de blog mentionne (édité un peu pour utiliser l’hôte et le plugin créés avec cette réponse):

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

     ├── [email protected] └─┬ [email protected] └── [email protected] 

    Je laisserai les échecs subtils provenant du plug-in en utilisant une autre API [HostLibraryX] que l’application principale de votre imagination.

    … 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 sympa pour inclure des informations de dépendance pour tous ses plugins, cela résoudrait le problème, mais cela introduirait également un nouveau problème culturel majeur : la gestion des plugins!

    L’intérêt des plugins réside dans le fait qu’ils peuvent être associés de manière anonyme. Dans un monde parfait, le fait que l’hôte les gère tous serait bien rangé, mais nous ne demanderons pas aux bibliothèques de devenir des chats.

    Si nous ne sums pas hiérarchiquement dépendants, peut-être sums-nous des pairs indépendants …

    Au lieu de cela, nous avons le concept d’être des pairs. Ni l’hôte ni le plug-in ne se trouvent dans le compartiment de dépendance de l’autre. Les deux vivent au même niveau que le graphe de dépendance.

    … mais ce n’est pas une relation automatisable.

    Si je suis PluginX v1 et que j’attends un homologue de HostLibraryX v3 (c’est-à-dire ayant une dépendance à l’égard des HostLibraryX v3 ), je le dirai. Si vous avez mis à niveau automatiquement vers la dernière version de HostLibraryX v4 (notez que c’est la version 4 ) ET que Plugin v1 installé, vous devez savoir, non?

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

    “Hé, je vois que vous utilisez PluginX v1 ! Je rétrograde automatiquement HostLibraryX de v4 à 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 si non, npm ?!

    Alors npm pas. Il vous avertit de la situation et vous permet de déterminer si HostLibraryX v4 est un pair approprié pour Plugin v1 .


    Coda

    Une bonne gestion peerDependency dans les plugins rendra ce concept plus intuitif dans la pratique. Du blog , encore une fois …

    Un conseil: les exigences de dépendance des pairs, à la différence de celles des dépendances régulières, devraient être indulgentes. Vous ne devez pas verrouiller vos dépendances entre pairs à des versions de correctifs spécifiques. Ce serait vraiment ennuyeux si un plug-in 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 leur temps à déterminer la version minimale de Chai. compatible avec.