web-dev-qa-db-fra.com

Pourquoi utiliser des dépendances entre homologues dans npm pour les plugins?

Pourquoi, par exemple, un plugin Grunt définit-il sa dépendance à grunt comme "dépendances entre homologues "?

Pourquoi le plugin ne peut-il pas simplement avoir Grunt comme sa propre dépendance dans grunt-plug/node_modules ?

Les dépendances entre homologues sont décrites ici: https://nodejs.org/fr/blog/npm/peer-dependencies/

Mais je ne comprends pas vraiment.

Exemple

Je travaille actuellement avec AppGyver Steroids, qui utilise des tâches Grunt pour créer mes fichiers source dans un dossier/dist/qui sera servi sur un périphérique local. Je suis tout à fait nouveau chez NPM et Grunt, alors je veux bien comprendre ce qui se passe.

Jusqu'à présent, j'ai ceci:

[dossier root] /package.json indique à npm que cela dépend du package grunt-steroids npm pour le développement:

  "devDependencies": {
    "grunt-steroids": "0.x"
  },

D'accord. L'exécution de npm install dans [dossier root] détecte la dépendance et installe grunt-steroids dans [dossier root]/node_modules/grunt. -stéroïdes .

Npm lit alors [dossier racine] /node_modules/grunt-steroids/package.json pour pouvoir installer grunt-steroids propres dépendances:

"devDependencies": {
    "grunt-contrib-nodeunit": "0.3.0",
    "grunt": "0.4.4"
  },
"dependencies": {
    "wrench": "1.5.4",
    "chalk": "0.3.0",
    "xml2js": "0.4.1",
    "lodash": "2.4.1"
  },
"peerDependencies": {
    "grunt": "0.4.4",
    "grunt-contrib-copy": "0.5.0",
    "grunt-contrib-clean": "0.5.0",
    "grunt-contrib-concat": "0.4.0",
    "grunt-contrib-coffee": "0.10.1",
    "grunt-contrib-sass": "0.7.3",
    "grunt-extend-config": "0.9.2"
  },

Les paquetages " dépendances " sont installés dans [dossier racine]/node_modules/grunt-steroids/node_modules ce qui est logique pour moi.

Les " devDependencies " ne sont pas installés, ce qui, j'en suis sûr, est contrôlé par la détection de npm. J'essaie juste d'utiliser grunt-steroids, et ne pas développer sur elle.

Mais alors nous avons le " peerDependencies ".

Ceux-ci sont installés dans [dossier root]/node_modules , et je ne comprends pas pourquoi et pas dans [dossier root ]/node_modules/grunt-steroids/node_modules afin d'éviter les conflits avec d'autres plugins Grunt (ou autre)?

173
Thomas Stock

TL; DR:[1] peerDependencies sont destinés aux dépendances exposées au code consommateur et devant être utilisées par celui-ci, par opposition aux dépendances "privées" qui ne sont pas exposés et ne constituent qu'un détail de la mise en œuvre.

Le problème des dépendances entre pairs

Le système de modules de NPM est hiérarchique. Un gros avantage pour les scénarios plus simples est que, lorsque vous installez un package npm, celui-ci comporte ses propres dépendances, de sorte qu'il fonctionne immédiatement.

Mais des problèmes se posent lorsque:

  • Votre projet et certains modules que vous utilisez dépendent d'un autre module.
  • Les trois modules doivent se parler.

Par exemple

Supposons que vous construisez YourCoolProject et que vous utilisiez à la fois JacksModule 1.0 et JillsModule 2.0. Et supposons que JacksModule dépend aussi de JillsModule, mais d'une version différente, disons 1.0. Tant que ces 2 versions ne se rencontrent pas, il n'y a pas de problème. Le fait que JacksModule utilise JillsModule sous la surface n'est qu'un détail de la mise en œuvre. Nous groupons JillsModule deux fois, mais c'est un petit prix à payer lorsque nous obtenons un logiciel stable immédiatement.

Mais maintenant, que se passe-t-il si JacksModule expose sa dépendance à JillsModule d'une manière ou d'une autre. Il accepte une instance de JillsClass par exemple ... Que se passe-t-il lorsque nous créons un new JillsClass en utilisant la version 2.0 de la bibliothèque et le transmettons à jacksFunction? Tout l'enfer va se déchaîner! Des choses simples comme jillsObject instanceof JillsClass renverront subitement false parce que jillsObject est en fait une instance de ne autreJillsClass, la version 2.0.

Comment les dépendances entre pairs résolvent ceci

Ils disent npm

J'ai besoin de ce paquet, mais j'ai besoin de la version qui fait partie du projet, pas d'une version privée de mon module.

Quand npm voit que votre paquet est en train d'être installé dans un projet qui ne possède pas cette dépendance, ou qui possède un version incompatible , il en avertira l’utilisateur pendant le processus d’installation.

Quand faut-il utiliser les dépendances entre pairs?

  • Lorsque vous construisez une bibliothèque qui sera utilisée par d'autres projets, et
  • Cette bibliothèque utilise une autre bibliothèque, et
  • Vous attendez/avez besoin que l'utilisateur travaille également avec cette autre bibliothèque

Les scénarios courants sont des plugins pour des cadres plus grands. Pensez à des choses comme Gulp, Grunt, Babel, Mocha, etc. Si vous écrivez un plugin Gulp, vous voulez que ce plugin fonctionne avec le même Gulp que le projet de l'utilisateur utilise, pas avec votre propre version privée de Gulp.


Annotations

  1. Trop long; n'a pas lu. Utilisé pour indiquer un court résumé pour un texte trop long.
343
Stijn de Witt

Je vous recommande de lire l'article à nouveau en premier. C'est un peu déroutant, mais l'exemple avec winston-mail vous montre pourquoi:

Par exemple, supposons que [email protected] ait spécifié "winston": "0.5.x" dans son objet "dependencies", car il s'agit de la dernière version sur laquelle il a été testé. En tant que développeur d’applications, vous souhaitez disposer des éléments les plus récents et les plus performants. Vous devez donc rechercher les dernières versions de winston et de winston-mail, puis les mettre dans votre package.json.

{
  "dependencies": {  
    "winston": "0.6.2",  
    "winston-mail": "0.2.3"  
  }  
}

Mais maintenant, l’exécution de l’installation de npm a pour résultat le graphe de dépendance inattendu de

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

Dans ce cas, il est possible d'avoir plusieurs versions d'un package, ce qui poserait problème. Les dépendances entre homologues permettent aux développeurs npm de s'assurer que l'utilisateur dispose du module spécifique (dans le dossier racine). Mais vous avez raison de dire que la description d'une version spécifique d'un paquet entraînerait des problèmes avec d'autres paquets utilisant d'autres versions. Ce problème concerne les développeurs npm, comme indiqué dans les articles

Un conseil : les exigences de dépendance entre pairs, contrairement à celles des dépendances régulières, doivent être indulgentes . Vous ne devez pas verrouiller vos dépendances entre homologues sur des versions de correctif spécifiques.

Par conséquent, les développeurs doivent suivre semver pour définir peerDependencies. Vous devriez ouvrir un problème pour le paquet grunt-steroids sur GitHub ...

23
Fer To

peerDependencies expliqué avec l'exemple le plus simple possible:

{
  "name": "myPackage",
  "dependencies": {
    "foo": "^4.0.0",
    "react": "^15.0.0"
  }
}


{
  "name": "foo"
  "peerDependencies": {
    "react": "^16.0.0"
  }
}

exécuter npm install dans myPackage provoquera une erreur car il tente d’installer React version ^15.0.0 ET foo qui n’est compatible qu’avec React ^16.0.0.

peerDependencies ne sont PAS installés.

6