Quelle est la différence entre Bower et npm?

1763

Quelle est la différence fondamentale entre boweret npm? Je veux juste quelque chose de clair et simple. J'ai vu certains de mes collègues utiliser boweret npminterchangeable dans leurs projets.

Games Brainiac
la source
7
Réponse connexe stackoverflow.com/a/21199026/1310070
sachinjain024
7
La réponse à cette question semble dépassée. Quelqu'un peut-il nous dire quoi faire en 2016 si nous utilisons npm 3 qui prend en charge la dépendance plate? Quelle est la différence entre npm3 et bower et quelle est la meilleure pratique en ce moment?
amdev
2
En résumé, @amdev: bower est désormais obsolète. npm (ou Yarn, ce qui n'est qu'une légère différence) est là où il en est. Je ne connais aucune alternative viable.
XML

Réponses:

1914

Tous les gestionnaires de packages présentent de nombreux inconvénients. Il vous suffit de choisir avec qui vous pouvez vivre.

Histoire

npm a commencé à gérer les modules node.js (c'est pourquoi les packages entrent node_modulespar défaut), mais cela fonctionne aussi pour le front-end lorsqu'il est combiné avec Browserify ou webpack .

Bower est créé uniquement pour le front-end et est optimisé dans cet esprit.

Taille du dépôt

npm est beaucoup, beaucoup plus grand que bower, y compris le JavaScript à usage général (comme country-datapour les informations sur le pays ou sortspour les fonctions de tri utilisables sur le front ou le back end).

Bower a une quantité beaucoup plus petite de paquets.

Gestion des styles, etc.

Bower comprend des styles, etc.

npm se concentre sur JavaScript. Les styles sont téléchargés séparément ou requis par quelque chose comme npm-sassou sass-npm.

Gestion des dépendances

La plus grande différence est que npm fait des dépendances imbriquées (mais est plat par défaut) tandis que Bower nécessite un arbre de dépendances plat (impose la charge de la résolution des dépendances à l'utilisateur) .

Un arbre de dépendances imbriqué signifie que vos dépendances peuvent avoir leurs propres dépendances qui peuvent avoir les leurs, et ainsi de suite. Cela permet à deux modules d'exiger des versions différentes de la même dépendance et de continuer à fonctionner. Notez que depuis npm v3, l'arborescence des dépendances sera par défaut plate (économisant de l'espace) et ne s'emboîtera que si nécessaire, par exemple, si deux dépendances ont besoin de leur propre version de Underscore.

Certains projets utilisent les deux, c'est qu'ils utilisent Bower pour les packages front-end et npm pour les outils de développement comme Yeoman, Grunt, Gulp, JSHint, CoffeeScript, etc.


Ressources

Sindre Sorhus
la source
37
Pourquoi un arbre de dépendances imbriqué ne fonctionne-t-il pas aussi bien sur le front-end?
Lars Nyström
24
Un package npm frontal ne pourrait-il pas être également un arbre de dépendance plat? Je suis confronté au "pourquoi avons-nous besoin de 2 gestionnaires de paquets?" dilemme.
Steven Vachon
38
Qu'entendez-vous par «arbre de dépendance plat»? L'arbre plat est quoi - une liste? Ce n'est pas un arbre alors.
mvmn
14
En fait, un chemin est aussi un arbre. C'est juste un cas spécial. De WikiPedia: "En mathématiques, et plus précisément en théorie des graphes, un arbre est un graphe non orienté dans lequel deux sommets sont connectés par exactement un chemin."
Jørgen Fogh
42
npm 3 prend désormais en charge un arbre de dépendance plat.
vasa
361

Cette réponse est un ajout à la réponse de Sindre Sorhus. La principale différence entre npm et Bower est la façon dont ils traitent les dépendances récursives. Notez qu'ils peuvent être utilisés ensemble dans un seul projet.

Sur la FAQ npm : (lien archive.org du 6 septembre 2015)

Il est beaucoup plus difficile d'éviter les conflits de dépendance sans imbriquer les dépendances. Ceci est fondamental pour le fonctionnement de npm et s'est avéré être une approche extrêmement réussie.

Sur la page d'accueil de Bower :

Bower est optimisé pour le front-end. Bower utilise une arborescence de dépendances plate, ne nécessitant qu'une seule version pour chaque package, réduisant ainsi la charge de pages au minimum.

En bref, npm vise la stabilité. Bower vise une charge de ressources minimale. Si vous dessinez la structure de dépendance, vous verrez ceci:

npm:

project root
[node_modules] // default directory for dependencies
 -> dependency A
 -> dependency B
    [node_modules]
    -> dependency A

 -> dependency C
    [node_modules]
    -> dependency B
      [node_modules]
       -> dependency A 
    -> dependency D

Comme vous pouvez le voir, il installe récursivement certaines dépendances. La dépendance A a trois instances installées!

Tonnelle:

project root
[bower_components] // default directory for dependencies
 -> dependency A
 -> dependency B // needs A
 -> dependency C // needs B and D
 -> dependency D

Ici, vous voyez que toutes les dépendances uniques sont au même niveau.

Alors, pourquoi s'embêter à utiliser npm?

La dépendance B nécessite peut-être une version de la dépendance A différente de celle de la dépendance C. npm installe les deux versions de cette dépendance afin que cela fonctionne de toute façon, mais Bower vous donnera un conflit car il n'aime pas la duplication (car le chargement de la même ressource sur une page Web est très inefficace et coûteux, cela peut aussi donner de graves erreurs). Vous devrez choisir manuellement la version que vous souhaitez installer. Cela peut avoir pour effet de briser l'une des dépendances, mais c'est quelque chose que vous devrez de toute façon corriger.

Ainsi, l'utilisation courante est Bower pour les packages que vous souhaitez publier sur vos pages Web (par exemple, à l' exécution , où vous évitez la duplication), et utilisez npm pour d'autres choses, comme les tests, la construction, l'optimisation, la vérification, etc. (par exemple , le temps de développement , où la duplication est moins préoccupante).

Mise à jour pour npm 3:

npm 3 fait toujours les choses différemment de Bower. Il installera les dépendances globalement, mais uniquement pour la première version rencontrée. Les autres versions sont installées dans l'arborescence (le module parent, puis node_modules).

  • [node_modules]
    • dep A v1.0
    • dep B v1.0
      • dep A v1.0 (utilise la version racine)
    • dep C v1.0
      • dep A v2.0 (cette version est différente de la version racine, donc ce sera une installation imbriquée)

Pour plus d'informations, je vous suggère de lire la documentation de npm 3

Justus Romijn
la source
4
C'est presque un cliché maintenant que «le développement de logiciels est une question de compromis». C'est un bon exemple. Il faut choisir soit une plus grande stabilité avec, npm soit une charge de ressources minimale avec bower.
jfmercer
6
@Shrek Je déclare implicitement que vous pouvez réellement utiliser les deux. Ils ont des objectifs différents, comme je le déclare dans le dernier paragraphe. Ce n'est pas un compromis à mes yeux.
Justus Romijn
Ahh, je vois que je vous ai mal compris. Ou je n'ai pas lu assez attentivement. Merci pour la clarification. :-) C'est bien que les deux puissent être utilisés sans compromis.
jfmercer
4
@AlexAngas J'ai ajouté une mise à jour pour npm3. Il présente encore quelques différences majeures par rapport à Bower. npm supportera probablement toujours plusieurs versions des dépendances, contrairement à Bower.
Justus Romijn
npm 3 se rapproche de bower;)
ni3
269

TL; DR: La plus grande différence dans l'utilisation quotidienne n'est pas les dépendances imbriquées ... c'est la différence entre les modules et les globaux.

Je pense que les affiches précédentes ont bien couvert certaines des distinctions de base. (L'utilisation par npm des dépendances imbriquées est en effet très utile dans la gestion d'applications volumineuses et complexes, bien que je ne pense pas que ce soit la distinction la plus importante.)

Je suis surpris, cependant, que personne n'ait explicitement expliqué l'une des distinctions les plus fondamentales entre Bower et npm. Si vous lisez les réponses ci-dessus, vous verrez le mot «modules» souvent utilisé dans le contexte de npm. Mais il est mentionné avec désinvolture, comme s'il pouvait même ne s'agir que d'une différence de syntaxe.

Mais cette distinction entre modules et globaux (ou modules vs 'scripts') est probablement la différence la plus importante entre Bower et npm. L'approche npm de tout mettre en modules vous oblige à changer la façon dont vous écrivez Javascript pour le navigateur, presque certainement pour le mieux.

The Bower Approach: Global Resources, Like <script>Tags

À la racine, Bower consiste à charger des fichiers de script anciens. Quels que soient ces fichiers de script, Bower les chargera. Ce qui signifie fondamentalement que Bower revient à inclure tous vos scripts dans les anciens <script>dans le <head>code HTML.

Donc, même approche de base à laquelle vous êtes habitué, mais vous obtenez de belles commodités d'automatisation:

  • Auparavant, vous deviez inclure des dépendances JS dans le référentiel de votre projet (pendant le développement) ou les obtenir via CDN. Maintenant, vous pouvez ignorer ce poids de téléchargement supplémentaire dans le référentiel, et quelqu'un peut faire rapidement bower installet instantanément ce dont il a besoin, localement.
  • Si une dépendance Bower spécifie alors ses propres dépendances dans celles-ci bower.json, celles-ci seront également téléchargées pour vous.

Mais au-delà de cela, Bower ne change pas la façon dont nous écrivons javascript . Rien sur ce qui se trouve à l'intérieur des fichiers chargés par Bower n'a besoin de changer du tout. En particulier, cela signifie que les ressources fournies dans les scripts chargés par Bower seront (généralement, mais pas toujours) toujours définies comme des variables globales , disponibles de n'importe où dans le contexte d'exécution du navigateur.

L'approche npm: modules JS communs, injection de dépendance explicite

Tout le code dans Node Land (et donc tout le code chargé via npm) est structuré en modules (en particulier, en tant qu'implémentation du format de module CommonJS , ou maintenant en tant que module ES6). Donc, si vous utilisez NPM pour gérer les dépendances côté navigateur (via Browserify ou autre chose qui fait le même travail), vous structurerez votre code de la même manière que Node.

Des gens plus intelligents que moi ont abordé la question «Pourquoi les modules?», Mais voici un résumé de la capsule:

  • Tout ce qui se trouve à l'intérieur d'un module est effectivement à espace de noms , ce qui signifie que ce n'est plus une variable globale, et vous ne pouvez pas le référencer accidentellement sans le vouloir.
  • Tout ce qui se trouve à l'intérieur d'un module doit être intentionnellement injecté dans un contexte particulier (généralement un autre module) afin de pouvoir l'utiliser.
  • Cela signifie que vous pouvez avoir plusieurs versions de la même dépendance externe (lodash, disons) dans diverses parties de votre application, et elles ne se heurteront pas / n'entreront pas en conflit. (Cela se produit souvent de manière surprenante, car votre propre code veut utiliser une version d'une dépendance, mais l'une de vos dépendances externes spécifie une autre qui est en conflit. Ou vous avez deux dépendances externes qui veulent chacune une version différente.)
  • Parce que toutes les dépendances sont injectées manuellement dans un module particulier, il est très facile de les raisonner. Vous savez pour un fait: "Le seul code que je dois considérer lorsque je travaille sur ce point est ce que j'ai intentionnellement choisi d'injecter ici" .
  • Parce que même le contenu des modules injectés est encapsulé derrière la variable à laquelle vous l'assignez et que tout le code s'exécute dans une portée limitée, les surprises et les collisions deviennent très improbables. Il est beaucoup, beaucoup moins probable que quelque chose de l'une de vos dépendances redéfinisse accidentellement une variable globale sans que vous vous en rendiez compte, ou que vous le fassiez. (Cela peut arriver, mais vous devez généralement faire tout votre possible pour le faire, avec quelque chose comme window.variable. Le seul accident qui a toujours tendance à se produire est l'attribution this.variable, sans se rendre compte que thisc'est en fait windowdans le contexte actuel.)
  • Lorsque vous souhaitez tester un module individuel, vous pouvez très facilement savoir: exactement quoi d'autre (dépendances) affecte le code qui s'exécute à l'intérieur du module? Et, comme vous injectez tout explicitement, vous pouvez facilement vous moquer de ces dépendances.

Pour moi, l'utilisation de modules pour le code frontal se résume à: travailler dans un contexte beaucoup plus étroit, plus facile à raisonner et à tester, et avoir une plus grande certitude sur ce qui se passe.


Il ne faut que 30 secondes environ pour apprendre à utiliser la syntaxe du module CommonJS / Node. Dans un fichier JS donné, qui va être un module, vous déclarez d'abord toutes les dépendances extérieures que vous souhaitez utiliser, comme ceci:

var React = require('react');

À l'intérieur du fichier / module, vous faites ce que vous feriez normalement et créez un objet ou une fonction que vous voudrez exposer à des utilisateurs extérieurs, en l'appelant peut-être myModule.

À la fin d'un fichier, vous exportez tout ce que vous voulez partager avec le monde, comme ceci:

module.exports = myModule;

Ensuite, pour utiliser un flux de travail basé sur CommonJS dans le navigateur, vous utiliserez des outils comme Browserify pour saisir tous ces fichiers de module individuels, encapsuler leur contenu au moment de l'exécution et les injecter les uns dans les autres selon les besoins.

ET, étant donné que les modules ES6 (que vous transposerez probablement vers ES5 avec Babel ou similaire) sont de plus en plus acceptés et fonctionnent à la fois dans le navigateur ou dans Node 4.0, nous devons également en mentionner un bon aperçu .

En savoir plus sur les modèles de travail avec les modules dans ce deck .


EDIT (février 2017): Facebook's Yarn est un remplacement / supplément potentiel très important pour npm ces jours-ci: une gestion de paquets rapide, déterministe et hors ligne qui s'appuie sur ce que npm vous offre. Cela vaut la peine de regarder n'importe quel projet JS, d'autant plus qu'il est si facile de l'échanger.


EDIT (mai 2019) "Bower a finalement été déconseillé . Fin de l'histoire." (h / t: @DanDascalescu, ci-dessous, pour un résumé concis.)

Et, alors que Yarn est toujours actif , une grande partie de l'élan pour le retour à npm une fois qu'il a adopté certaines des fonctionnalités clés de Yarn.

XML
la source
13
Heureux que cette réponse soit là, les autres réponses populaires ne mentionnent pas ce détail. npm vous oblige à écrire du code modulaire.
Juan Mendes
Je suis désolé, d'un peuple qui se soucie très peu de tout le fuzzing dans les parlands javascript mais il se trouve qu'il gère une entreprise qui utilise une petite application Web. Récemment, j'ai été forcé d'essayer npm, d'utiliser bower avec la boîte à outils que nous utilisons pour développer le truc du web. Je peux vous dire que la plus grande différence est le temps d'attente, le npm prend beaucoup de temps. Rappelez-vous que compile un dessin animé xkcd avec des gars qui jouent à des combats à l'épée en criant «compiler» à leur patron; c'est à peu près ce que npm a ajouté à bower.
Pedro Rodrigues
129

Mise à jour 2017-octobre

Bower a finalement été déprécié . Fin de l'histoire.

Réponse plus ancienne

De Mattias Petter Johansson, développeur JavaScript chez Spotify :

Dans presque tous les cas, il est plus approprié d'utiliser Browserify et npm sur Bower. Il s'agit simplement d'une meilleure solution d'emballage pour les applications frontales que Bower. Chez Spotify, nous utilisons npm pour emballer des modules Web entiers (html, css, js) et cela fonctionne très bien.

Bower se présente comme le gestionnaire de packages pour le Web. Ce serait génial si cela était vrai - un gestionnaire de packages qui a amélioré ma vie en tant que développeur frontal serait génial. Le problème est que Bower n'offre aucun outillage spécialisé à cet effet. Il n'offre AUCUN outillage que je connais que npm ne propose, et surtout aucun qui soit spécifiquement utile pour les développeurs front-end. Il n'y a tout simplement aucun avantage pour un développeur frontal à utiliser Bower sur npm.

Nous devrions cesser d'utiliser bower et consolider vers npm. Heureusement, c'est ce qui se passe :

Nombre de modules - bower vs npm

Avec browserify ou webpack, il devient super facile de concaténer tous vos modules en gros fichiers minifiés, ce qui est génial pour les performances, en particulier pour les appareils mobiles. Ce n'est pas le cas avec Bower, qui nécessitera beaucoup plus de travail pour obtenir le même effet.

npm vous offre également la possibilité d'utiliser plusieurs versions de modules simultanément. Si vous n'avez pas fait beaucoup de développement d'applications, cela pourrait vous sembler initialement une mauvaise chose, mais une fois que vous aurez traversé quelques épisodes d' enfer de dépendance, vous vous rendrez compte qu'avoir la possibilité d'avoir plusieurs versions d'un module est un sacré sacré grande fonctionnalité. Notez que npm inclut un outil de déduplication très pratique qui garantit automatiquement que vous n'utilisez que deux versions d'un module si vous en avez réellement besoin - si deux modules peuvent tous deux utiliser la même version d'un module, ils le feront. Mais s'ils ne le peuvent pas , vous en avez un très pratique.

(Notez que Webpack et rollup sont largement considérés comme meilleurs que Browserify en août 2016.)

Dan Dascalescu
la source
7
<sarcasm> N'oubliez pas que même le projet npm 'hello world' nécessite plus de 300 modules pour fonctionner ... </sarcasm>: O
Mariusz Jamro
1
Je ne suis pas d'accord pour dire que les "gros fichiers minifiés" sont "géniaux pour les performances, en particulier pour les appareils mobiles". Bien au contraire: une bande passante restreinte nécessite de petits fichiers, chargés à la demande.
Michael Franzl
Pas de très bons conseils. La plupart des packages npm sont uniquement des backends nodejs. Si vous ne faites pas de javascript sur le backend, ou si vous n'avez pas de système de module en place, le nombre de packages n'est pas pertinent car Bower répondra bien mieux à vos besoins
Gerardo Grignoli
4
@GerardoGrignoli: bower est sur le point de disparaître .
Dan Dascalescu du
45

Bower gère une seule version des modules, il essaie seulement de vous aider à sélectionner le bon / meilleur pour vous.

Gestion des dépendances Javascript: npm vs bower vs volo?

NPM est meilleur pour les modules de nœuds car il existe un système de modules et vous travaillez localement. Bower est bon pour le navigateur car il n'y a actuellement qu'une portée globale et vous voulez être très sélectif sur la version avec laquelle vous travaillez.

Sagivf
la source
4
Je pense que Sindre le mentionne quand il parle de dépendance imbriquée.
Games Brainiac
5
@GamesBrainiac, vous avez raison, je pensais simplement que je le mettrais dans mes propres mots.
Sagivf
1
@Sagivf Ce ne sont PAS vos propres mots, à moins que vous ne soyez également ceux qui ont fourni la réponse originale ici
Dayuloli
4
@Sagivf Il n'y a rien de mal à copier ** les parties pertinentes des réponses des autres s'ils n'ont pas fourni de réponse ici eux-mêmes. Cela m'a un peu dérangé, vous avez dit "je pensais simplement que je le mettrais dans mes propres mots." Le crédit doit aller là où il est dû.
dayuloli
2
Je ne sais pas pourquoi vous avez tant choisi cette réponse. Il y a en effet de nouvelles informations / perspectives dans cette réponse pour moi.
Calvin
33

Mon équipe s'est éloignée de Bower et a migré vers npm parce que:

  • L'utilisation programmatique était douloureuse
  • L'interface de Bower n'a cessé de changer
  • Certaines fonctionnalités, comme le raccourci URL, sont entièrement cassées
  • Utiliser à la fois Bower et npm dans le même projet est douloureux
  • Garder le champ de version de bower.json synchronisé avec les balises git est pénible
  • Contrôle de source! = Gestion des paquets
  • Le support CommonJS n'est pas simple

Pour plus de détails, voir "Pourquoi mon équipe utilise npm au lieu de bower" .

Nick Heiner
la source
17

Trouvé cette explication utile sur http://ng-learn.org/2013/11/Bower-vs-npm/

D'une part, npm a été créé pour installer des modules utilisés dans un environnement node.js, ou des outils de développement construits en utilisant node.js tels que Karma, lint, minifiers et ainsi de suite. npm peut installer des modules localement dans un projet (par défaut dans node_modules) ou globalement pour être utilisé par plusieurs projets. Dans les grands projets, la façon de spécifier les dépendances consiste à créer un fichier appelé package.json qui contient une liste de dépendances. Cette liste est reconnue par npm lorsque vous exécutez npm install, qui les télécharge et les installe ensuite pour vous.

D'un autre côté, bower a été créé pour gérer vos dépendances frontales. Des bibliothèques comme jQuery, AngularJS, underscore, etc. Similaire à npm, il a un fichier dans lequel vous pouvez spécifier une liste de dépendances appelée bower.json. Dans ce cas, vos dépendances frontales sont installées en exécutant bower install qui les installe par défaut dans un dossier appelé bower_components.

Comme vous pouvez le voir, bien qu'ils effectuent une tâche similaire, ils sont destinés à un ensemble très différent de bibliothèques.

Henry Neo
la source
1
Avec l'avènement de npm dedupe, c'est un peu dépassé. Voir la réponse de Mattias .
Dan Dascalescu
7

Pour de nombreuses personnes travaillant avec node.js, un avantage majeur de bower est la gestion des dépendances qui ne sont pas du tout javascript. S'ils travaillent avec des langages qui se compilent en javascript, npm peut être utilisé pour gérer certaines de leurs dépendances. cependant, toutes leurs dépendances ne seront pas des modules node.js. Certains de ceux qui compilent en javascript peuvent avoir une manipulation étrange spécifique à la langue source qui fait de leur compilation compilée en javascript une option inélégante lorsque les utilisateurs attendent du code source.

Tout ce qui se trouve dans un package npm n'a pas besoin d'être javascript accessible à l'utilisateur, mais pour les packages de bibliothèque npm, au moins une partie devrait l'être.

jessopher
la source
Ce billet de blog npmjs déclare "Votre package peut contenir n'importe quoi, que ce soit ES6, JS côté client, ou même HTML et CSS. Ce sont des choses qui se présentent naturellement aux côtés de JavaScript, alors mettez-les dedans.".
Dan Dascalescu
1
Il existe une différence entre peut contenir et devrait inclure . Bien sûr, ils peuvent contenir n'importe quoi, mais en général, ils devraient inclure une sorte d'interface avec commonJS. C'est le «gestionnaire de paquets de nœuds» après tout. La partie concernant Ce sont des choses qui apparaissent naturellement aux côtés de Javascript est importante. Il y a beaucoup de choses tangentiellement liées au javascript qui n'apparaissent pas naturellement à ses côtés .
jessopher