Qual è la differenza tra Bower e npm?


1763

Qual è la differenza fondamentale tra bowere npm? Voglio solo qualcosa di chiaro e semplice. Ho visto alcuni dei miei colleghi usare bowere in modo npmintercambiabile nei loro progetti.




7
La risposta a questa domanda sembra obsoleta. Qualcuno può dirci cosa fare nel 2016 se utilizziamo npm 3 che supporta la dipendenza flat? Qual è la differenza tra npm3 e bower e qual è la migliore pratica in questo momento?
amdev,

2
In conclusione, @amdev: il bower è ora deprecato. npm (o Filato, che è solo una leggera differenza) è dove si trova. Non sono a conoscenza di alternative praticabili.
XML

Risposte:


1914

Tutti i gestori di pacchetti hanno molti aspetti negativi. Devi solo scegliere con chi vivere.

Storia

npm ha iniziato a gestire i moduli node.js (ecco perché i pacchetti entrano node_modulesper impostazione predefinita), ma funziona anche per il front-end quando combinato con Browserify o webpack .

Bower è creato esclusivamente per il front-end ed è ottimizzato tenendo presente questo aspetto.

Dimensione del repo

npm è molto, molto più grande del pergolato, incluso JavaScript per uso generale (come country-dataper le informazioni sul paese o sortsper le funzioni di ordinamento utilizzabili sul front-end o sul back-end).

Bower ha una quantità molto più piccola di pacchetti.

Gestione degli stili ecc

Bower include stili ecc.

npm è focalizzato su JavaScript. Gli stili possono essere scaricati separatamente o richiesti da qualcosa di simile npm-sasso sass-npm.

Gestione delle dipendenze

La differenza più grande è che npm fa dipendenze nidificate (ma è piatta per impostazione predefinita) mentre Bower richiede un albero delle dipendenze piatto (pone l'onere della risoluzione delle dipendenze sull'utente) .

Un albero delle dipendenze nidificato significa che le dipendenze possono avere le proprie dipendenze che possono avere le proprie e così via. Ciò consente a due moduli di richiedere versioni diverse della stessa dipendenza e di funzionare ancora. Nota da npm v3, l'albero delle dipendenze sarà piatto per impostazione predefinita (risparmiando spazio) e nidificherà solo dove necessario, ad esempio, se due dipendenze hanno bisogno della propria versione di Underscore.

Alcuni progetti usano entrambi è che usano Bower per i pacchetti front-end e npm per strumenti di sviluppo come Yeoman, Grunt, Gulp, JSHint, CoffeeScript, ecc.


risorse


37
Perché un albero delle dipendenze nidificato non funziona così bene sul front-end?
Lars Nyström,

24
Un pacchetto npm front-end potrebbe non essere anche un albero delle dipendenze piatto? Sto affrontando il "perché abbiamo bisogno di 2 gestori di pacchetti?" dilemma.
Steven Vachon,

38
Cosa intendi con "albero piatto delle dipendenze"? L'albero piatto è cosa: un elenco? Allora non è un albero.
mvmn,

14
In realtà, un percorso è anche un albero. È solo un caso speciale. Da WikiPedia: "In matematica, e più precisamente nella teoria dei grafi, un albero è un grafico non orientato in cui due vertici sono collegati esattamente da un percorso".
Jørgen Fogh,

42
npm 3 ora supporta un albero delle dipendenze piatto.
Vasa,

361

Questa risposta è un'aggiunta alla risposta di Sindre Sorhus. La principale differenza tra npm e Bower è il modo in cui trattano le dipendenze ricorsive. Si noti che possono essere utilizzati insieme in un singolo progetto.

Sulle FAQ di npm : (collegamento archive.org dal 6 settembre 2015)

È molto più difficile evitare conflitti di dipendenza senza nidificare dipendenze. Questo è fondamentale per il modo in cui npm funziona e ha dimostrato di essere un approccio estremamente efficace.

Sulla homepage di Bower :

Bower è ottimizzato per il front-end. Bower utilizza un albero delle dipendenze piatto, che richiede solo una versione per ciascun pacchetto, riducendo al minimo il carico della pagina.

In breve, npm punta alla stabilità. Bower mira a un carico di risorse minimo. Se disegni la struttura delle dipendenze, vedrai questo:

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

Come puoi vedere, installa alcune dipendenze in modo ricorsivo. La dipendenza A ha tre istanze installate!

Bower:

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

Qui vedi che tutte le dipendenze uniche sono sullo stesso livello.

Quindi, perché preoccuparsi di usare npm?

Forse la dipendenza B richiede una versione diversa della dipendenza A rispetto alla dipendenza C. npm installa entrambe le versioni di questa dipendenza, quindi funzionerà comunque, ma Bower ti darà un conflitto perché non gli piace la duplicazione (perché il caricamento della stessa risorsa su una pagina web è molto inefficiente e costoso, inoltre può dare alcuni errori gravi). Dovrai scegliere manualmente quale versione vuoi installare. Questo può avere l'effetto che una delle dipendenze si romperà, ma è comunque qualcosa che dovrai correggere.

Pertanto, l'uso comune è Bower per i pacchetti che si desidera pubblicare sulle proprie pagine Web (ad es. Runtime , dove si evita la duplicazione) e utilizzare npm per altre cose, come test, costruzione, ottimizzazione, controllo, ecc. (Ad es. Tempo di sviluppo , in cui la duplicazione è meno preoccupante).

Aggiornamento per npm 3:

npm 3 fa ancora cose diversamente rispetto a Bower. Installerà le dipendenze a livello globale, ma solo per la prima versione che incontra. Le altre versioni sono installate nell'albero (il modulo padre, quindi node_modules).

  • [Node_modules]
    • dep A v1.0
    • dep B v1.0
      • dep A v1.0 (usa la versione root)
    • dep C v1.0
      • dep A v2.0 (questa versione è diversa dalla versione root, quindi sarà un'installazione nidificata)

Per ulteriori informazioni, suggerisco di leggere i documenti di npm 3


4
È quasi un cliché ora che "lo sviluppo del software è tutto basato su compromessi". Questo è un buon esempio Bisogna scegliere una maggiore stabilità con npm o un carico minimo di risorse con bower.
jfmercer,

6
@Shrek Sto implicitamente affermando che puoi effettivamente usare entrambi. Hanno scopi diversi, come dichiaro nel paragrafo finale. Non è un compromesso ai miei occhi.
Justus Romijn il

Ahh, vedo che ti ho frainteso. O non ho letto abbastanza attentamente. Grazie per il chiarimento. :-) È positivo che entrambi possano essere utilizzati senza un compromesso.
jfmercer,

4
@AlexAngas Ho aggiunto un aggiornamento per npm3. Ha ancora alcune differenze importanti rispetto a Bower. npm probabilmente supporterà sempre più versioni di dipendenze, mentre Bower no.
Justus Romijn il

npm 3 si avvicina al pergolato;)
ni3

269

TL; DR: la più grande differenza nell'uso quotidiano non sono le dipendenze nidificate ... è la differenza tra moduli e globali.

Penso che i poster precedenti abbiano coperto bene alcune delle distinzioni di base. (l'uso delle dipendenze nidificate da parte di npm è davvero molto utile nella gestione di applicazioni grandi e complesse, anche se non credo sia la distinzione più importante.)

Sono sorpreso, tuttavia, che nessuno abbia esplicitamente spiegato una delle distinzioni più fondamentali tra Bower e npm. Se leggi le risposte sopra, vedrai la parola 'moduli' usata spesso nel contesto di npm. Ma è menzionato casualmente, come se potesse anche essere solo una differenza di sintassi.

Ma questa distinzione tra moduli e globuli (o moduli vs. "script") è forse la differenza più importante tra Bower e npm. L'approccio npm di mettere tutto nei moduli richiede di cambiare il modo in cui scrivi Javascript per il browser, quasi sicuramente in meglio.

L'approccio di Bower: risorse globali, come <script>tag

Alla radice, Bower riguarda il caricamento di file di script semplici. Qualsiasi cosa contengano questi file di script, Bower li caricherà. Il che significa sostanzialmente che Bower è come includere tutti i tuoi script in quelli semplici <script>nel <head>tuo HTML.

Quindi, lo stesso approccio di base a cui sei abituato, ma ottieni alcune belle comodità di automazione:

  • In passato era necessario includere dipendenze JS nel repository del progetto (durante lo sviluppo) o ottenerle tramite CDN. Ora, puoi saltare quel peso aggiuntivo per il download nel repository e qualcuno può fare rapidamente bower installe avere immediatamente ciò di cui hanno bisogno, localmente.
  • Se una dipendenza Bower specifica quindi le proprie dipendenze nelle sue bower.json, quelle verranno scaricate anche per te.

Ma oltre a ciò, Bower non cambia il modo in cui scriviamo javascript . Nulla di ciò che accade all'interno dei file caricati da Bower deve cambiare affatto. In particolare, ciò significa che le risorse fornite negli script caricati da Bower saranno (di solito, ma non sempre) ancora definite come variabili globali , disponibili da qualsiasi parte nel contesto di esecuzione del browser.

L'approccio npm: moduli JS comuni, iniezione di dipendenza esplicita

Tutto il codice in Node land (e quindi tutto il codice caricato tramite npm) è strutturato come moduli (in particolare, come implementazione del formato del modulo CommonJS , o ora, come modulo ES6). Quindi, se usi NPM per gestire le dipendenze sul lato browser (tramite Browserify o qualcos'altro che fa lo stesso lavoro), strutturerai il tuo codice allo stesso modo di Node.

Le persone più intelligenti di me hanno affrontato la domanda "Perché i moduli?", Ma ecco un riassunto delle capsule:

  • Qualunque cosa all'interno di un modulo è effettivamente spaziata dal nome , il che significa che non è più una variabile globale, e non puoi fare riferimento accidentalmente senza volerlo.
  • Qualunque cosa all'interno di un modulo deve essere intenzionalmente iniettata in un particolare contesto (di solito un altro modulo) per poterlo utilizzare
  • Ciò significa che puoi avere più versioni della stessa dipendenza esterna (lodash, diciamo) in varie parti dell'applicazione e che non si scontreranno / non entreranno in conflitto. (Ciò accade sorprendentemente spesso, perché il tuo codice vuole usare una versione di una dipendenza, ma una delle tue dipendenze esterne ne specifica un'altra che è in conflitto. O hai due dipendenze esterne che vogliono una versione diversa.)
  • Poiché tutte le dipendenze vengono iniettate manualmente in un determinato modulo, è molto facile ragionare su di esse. Sai per certo : "L'unico codice che devo considerare quando lavoro su questo è ciò che ho scelto di iniettare qui intenzionalmente" .
  • Poiché anche il contenuto dei moduli iniettati è incapsulato dietro la variabile a cui lo assegni e tutto il codice viene eseguito in un ambito limitato, sorprese e collisioni diventano molto improbabili. È molto, molto meno probabile che qualcosa da una delle tue dipendenze ridefinisca accidentalmente una variabile globale senza che te ne accorga, o che lo farai. ( Può succedere, ma di solito devi fare di tutto per farlo, con qualcosa del genere window.variable. L'unico incidente che tende ancora a verificarsi è l'assegnazione this.variable, non rendendosi conto che in thisrealtà è windownel contesto attuale.)
  • Quando vuoi testare un singolo modulo, sei in grado di sapere molto facilmente: esattamente cos'altro (dipendenze) sta influenzando il codice che gira all'interno del modulo? E, poiché stai esplicitamente iniettando tutto, puoi facilmente deridere quelle dipendenze.

Per me, l'uso dei moduli per il codice front-end si riduce a: lavorare in un contesto molto più ristretto che è più facile ragionare e testare e avere una maggiore certezza su ciò che sta succedendo.


Ci vogliono solo circa 30 secondi per imparare a usare la sintassi del modulo CommonJS / Node. All'interno di un determinato file JS, che sarà un modulo, devi prima dichiarare qualsiasi dipendenza esterna che desideri utilizzare, in questo modo:

var React = require('react');

All'interno del file / modulo, fai quello che faresti normalmente e crei qualche oggetto o funzione che vorresti esporre agli utenti esterni, chiamandolo forse myModule.

Alla fine di un file, esporti tutto ciò che vuoi condividere con il mondo, in questo modo:

module.exports = myModule;

Quindi, per utilizzare un flusso di lavoro basato su CommonJS nel browser, utilizzerai strumenti come Browserify per afferrare tutti quei singoli file del modulo, incapsulare i loro contenuti in fase di esecuzione e inserirli l'uno nell'altro secondo necessità.

E, poiché i moduli ES6 (che probabilmente traspilerai in ES5 con Babel o simili) stanno ottenendo ampia accettazione e funzionano sia nel browser che nel Nodo 4.0, dovremmo menzionare anche una buona panoramica di quelli.

Altre informazioni sui modelli per lavorare con i moduli in questo mazzo .


EDIT (febbraio 2017): Yarn di Facebook è un potenziale sostitutivo / integratore molto importante per npm in questi giorni: gestione dei pacchetti veloce, deterministica e offline che si basa su ciò che npm ti offre. Vale la pena dare un'occhiata a qualsiasi progetto JS, soprattutto perché è così facile scambiarlo.


EDIT (maggio 2019) "Bower è stato finalmente deprecato . Fine della storia." (h / t: @DanDascalescu, sotto, per il riepilogo pithy.)

E, mentre Yarn è ancora attivo , gran parte dello slancio è tornato a npm dopo aver adottato alcune delle funzionalità principali di Yarn.


13
Sono contento che questa risposta fosse qui, le altre risposte popolari non menzionano questo dettaglio. npm ti obbliga a scrivere codice modulare.
Juan Mendes,

Mi dispiace, da una gente che si preoccupa molto poco di tutto il fuzzing nelle terre javascript ma così succede che gestisce un'azienda che si avvale di una piccola applicazione web. Recentemente sono stato costretto a provare npm, dall'uso di bower con il toolkit che usiamo per sviluppare la maledetta cosa del web. Posso dirti che la differenza più grande è il tempo di attesa, npm richiede anni. Ricorda che sta compilando un fumetto xkcd con i ragazzi che giocano a combattimenti con la spada urlando "compilando" al loro capo; questo è praticamente ciò che npm ha aggiunto a Bower.
Pedro Rodrigues,

129

Aggiornamento 2017-ottobre

Bower è stato finalmente deprecato . Fine della storia.

Risposta precedente

Da Mattias Petter Johansson, sviluppatore JavaScript di Spotify :

In quasi tutti i casi, è più appropriato utilizzare Browserify e npm su Bower. È semplicemente una soluzione di packaging migliore per le app front-end rispetto a Bower. In Spotify, utilizziamo npm per impacchettare interi moduli web (html, css, js) e funziona molto bene.

Bower si afferma come gestore di pacchetti per il web. Sarebbe fantastico se questo fosse vero - un gestore di pacchetti che mi ha reso la vita migliore come sviluppatore front-end sarebbe fantastico. Il problema è che Bower non offre strumenti specifici per lo scopo. Non offre strumenti di cui io sappia che npm no, e in particolare nessuno che sia particolarmente utile per gli sviluppatori front-end. Semplicemente non c'è alcun vantaggio per uno sviluppatore front-end di utilizzare Bower su npm.

Dovremmo smettere di usare il pergolato e consolidarci intorno a npm. Per fortuna, è quello che sta succedendo :

Conteggio del modulo - bower vs. npm

Con browserify o webpack, diventa semplicissimo concatenare tutti i tuoi moduli in grandi file minimizzati, il che è fantastico per le prestazioni, specialmente per i dispositivi mobili. Non è così con Bower, che richiederà molto più lavoro per ottenere lo stesso effetto.

npm ti offre anche la possibilità di utilizzare più versioni di moduli contemporaneamente. Se non hai fatto molto sviluppo di applicazioni, questo potrebbe inizialmente sembrare una cosa negativa, ma una volta che hai attraversato alcuni episodi di inferno di dipendenza, ti renderai conto che avere la possibilità di avere più versioni di un modulo è un bel casino grande caratteristica. Si noti che npm include uno strumento dedupe molto utile che si assicura automaticamente di utilizzare solo due versioni di un modulo, se necessario - se due moduli possono entrambi utilizzare la stessa versione di un modulo, lo faranno. Ma se non ci riescono , hai una cosa molto utile.

(Si noti che Webpack e rollup sono ampiamente considerati migliori di Browserify a partire da agosto 2016.)


7
<sarcasm> Tieni presente che anche il progetto npm di 'ciao mondo' ha bisogno di oltre 300 moduli per funzionare ... </
sarcasm

1
Non sono d'accordo sul fatto che i "file di dimensioni ridotte" siano "eccezionali per le prestazioni, soprattutto per i dispositivi mobili". Al contrario: la larghezza di banda limitata richiede file di piccole dimensioni, caricati su richiesta.
Michael Franzl,

Consiglio non molto buono. La maggior parte dei pacchetti npm sono solo backend nodejs. Se non stai eseguendo javascript sul back-end o non hai un sistema di moduli in atto, il numero di pacchetti è irrilevante perché Bower si adatta molto meglio alle tue esigenze
Gerardo Grignoli,

4
@GerardoGrignoli: il pergolato sta per uscire .
Dan Dascalescu,

45

Bower mantiene una singola versione di moduli, cerca solo di aiutarti a selezionare quella giusta / migliore per te.

Gestione delle dipendenze Javascript: npm vs bower vs volo?

NPM è migliore per i moduli nodo perché esiste un sistema di moduli e si sta lavorando localmente. Bower è buono per il browser perché al momento esiste solo l'ambito globale e vuoi essere molto selettivo sulla versione con cui lavori.


4
Sento che Sindre lo menziona quando parla di dipendenza annidata.
Giochi Brainiac,

5
@GamesBrainiac hai ragione, ho pensato di dirlo con parole mie.
Sagivf,

1
@Sagivf NON sono parole tue, a meno che tu non sia anche il luogo in cui hai fornito la risposta originale qui
dayuloli

4
@Sagivf Non c'è niente di sbagliato nel copiare ** parti rilevanti delle risposte degli altri se non hanno fornito una risposta qui da soli. Mi ha solo infastidito un po 'hai detto "pensavo solo di dirlo con parole mie". Il credito dovrebbe andare dove è dovuto il credito.
Dayuloli

2
Non so perché avete scelto così tanto questa risposta. Ci sono davvero nuove informazioni / prospettive in questa risposta per me.
Calvin,

33

Il mio team si è allontanato da Bower ed è migrato su npm perché:

  • L'uso programmatico è stato doloroso
  • L'interfaccia di Bower continuava a cambiare
  • Alcune funzioni, come la scorciatoia dell'URL, sono completamente rotte
  • Usare sia Bower che npm nello stesso progetto è doloroso
  • Mantenere sincronizzato il campo della versione di bower.json con i tag git è doloroso
  • Controllo del codice sorgente = gestione dei pacchetti
  • Il supporto di CommonJS non è semplice

Per maggiori dettagli, vedi "Perché il mio team usa npm invece di bower" .


17

Ho trovato questa utile spiegazione da http://ng-learn.org/2013/11/Bower-vs-npm/

Da un lato npm è stato creato per installare moduli utilizzati in un ambiente node.js o strumenti di sviluppo creati utilizzando node.js come Karma, lint, minifiers e così via. npm può installare moduli localmente in un progetto (per impostazione predefinita in node_modules) o globalmente per essere utilizzato da più progetti. Nei progetti di grandi dimensioni, il modo per specificare le dipendenze consiste nel creare un file chiamato package.json che contiene un elenco di dipendenze. Tale elenco viene riconosciuto da npm quando si esegue npm install, che quindi li scarica e li installa.

D'altra parte, il pergolato è stato creato per gestire le dipendenze del frontend. Librerie come jQuery, AngularJS, carattere di sottolineatura, ecc. Simile a npm ha un file in cui è possibile specificare un elenco di dipendenze chiamato bower.json. In questo caso le dipendenze del tuo frontend vengono installate eseguendo bower install che per impostazione predefinita le installa in una cartella chiamata bower_components.

Come puoi vedere, sebbene eseguano un'attività simile, sono indirizzati a un set di librerie molto diverso.


1
Con l'avvento di npm dedupe, questo è un po 'obsoleto. Vedi la risposta di Mattias .
Dan Dascalescu il

7

Per molte persone che lavorano con node.js, un grande vantaggio di bower è la gestione delle dipendenze che non sono affatto javascript. Se stanno lavorando con lingue compilabili in javascript, npm può essere usato per gestire alcune delle loro dipendenze. tuttavia, non tutte le loro dipendenze saranno moduli node.js. Alcuni di quelli che vengono compilati in javascript possono presentare strane mangling specifiche della lingua di origine che li rendono un passaggio non compilato in javascript come un'opzione non elegante quando gli utenti si aspettano il codice sorgente.

Non tutto in un pacchetto npm deve essere javascript rivolto all'utente, ma per i pacchetti della libreria npm, almeno alcuni dovrebbero esserlo.


Questo post sul blog di npmjs afferma "Il tuo pacchetto può contenere qualsiasi cosa, sia ES6, JS lato client o persino HTML e CSS. Queste sono cose che si presentano naturalmente insieme a JavaScript, quindi inseriscile".
Dan Dascalescu il

1
C'è una differenza tra può contenere e dovrebbe includere . Naturalmente possono contenere qualsiasi cosa, ma in generale dovrebbero includere una sorta di interfaccia con commonJS. Dopotutto è il "gestore pacchetti nodo". La parte su Queste sono cose che si presentano naturalmente insieme a Javascript è importante. Ci sono molte cose che sono tangenzialmente correlate al javascript che non si presentano naturalmente al suo fianco .
jessopher,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.