¿Cuál es la diferencia entre Bower y npm?

1763

¿Cuál es la diferencia fundamental entre bowery npm? Solo quiero algo simple y llano. He visto a algunos de mis colegas usar bowere npmintercambiablemente en sus proyectos.

Juegos Brainiac
fuente
77
Respuesta relacionada stackoverflow.com/a/21199026/1310070
sachinjain024
44
posible duplicado de la gestión de dependencia
anotherdave
77
La respuesta a esta pregunta parece anticuada. ¿Alguien puede decirnos qué hacer en 2016 si utilizamos npm 3 que admiten dependencia plana? ¿Cuál es la diferencia wince npm3 y bower y cuál es la mejor práctica en este momento?
amdev
2
En pocas palabras, @amdev: bower ahora está en desuso. npm (o Yarn, que es solo una ligera diferencia) es donde está. No conozco ninguna alternativa viable.
XML

Respuestas:

1914

Todos los administradores de paquetes tienen muchas desventajas. Solo tienes que elegir con qué puedes vivir.

Historia

npm comenzó administrando módulos node.js (es por eso que los paquetes entran node_modulespor defecto), pero también funciona para el front-end cuando se combina con Browserify o webpack .

Bower está creado exclusivamente para el front-end y está optimizado teniendo esto en cuenta.

Tamaño del repositorio

npm es mucho, mucho más grande que Bower, incluido JavaScript de uso general (como country-datapara información del país o sortspara ordenar funciones que se pueden utilizar en el front-end o el back-end).

Bower tiene una cantidad mucho menor de paquetes.

Manejo de estilos, etc.

Bower incluye estilos, etc.

npm se centra en JavaScript. Los estilos se descargan por separado o son requeridos por algo como npm-sasso sass-npm.

Manejo de dependencias

La mayor diferencia es que npm tiene dependencias anidadas (pero es plana por defecto) mientras que Bower requiere un árbol de dependencias plano (pone la carga de la resolución de la dependencia en el usuario) .

Un árbol de dependencias anidado significa que sus dependencias pueden tener sus propias dependencias que pueden tener las suyas propias, y así sucesivamente. Esto permite que dos módulos requieran versiones diferentes de la misma dependencia y aún funcionen. Tenga en cuenta que desde npm v3, el árbol de dependencias quedará plano de forma predeterminada (ahorrando espacio) y solo se anidará donde sea necesario, por ejemplo, si dos dependencias necesitan su propia versión de subrayado.

Algunos proyectos usan ambos es que usan Bower para paquetes front-end y npm para herramientas de desarrollo como Yeoman, Grunt, Gulp, JSHint, CoffeeScript, etc.


Recursos

Sindre Sorhus
fuente
37
¿Por qué un árbol de dependencias anidado no funciona tan bien en el front-end?
Lars Nyström
24
¿Podría un paquete npm front-end no ser un árbol de dependencia plano también? Me enfrento al "¿por qué necesitamos 2 gestores de paquetes?" dilema.
Steven Vachon
38
¿Qué quieres decir con "árbol de dependencia plano"? ¿Qué es un árbol plano? ¿Una lista? No es un árbol entonces.
mvmn
14
En realidad, un camino también es un árbol. Es solo un caso especial. De WikiPedia: "En matemáticas, y más específicamente en teoría de grafos, un árbol es un gráfico no dirigido en el cual dos vértices están conectados por exactamente un camino".
Jørgen Fogh
42
npm 3 ahora admite un árbol de dependencia plano.
vasa
361

Esta respuesta es una adición a la respuesta de Sindre Sorhus. La principal diferencia entre npm y Bower es la forma en que tratan las dependencias recursivas. Tenga en cuenta que se pueden usar juntos en un solo proyecto.

En las preguntas frecuentes de npm : (enlace archive.org del 6 de septiembre de 2015)

Es mucho más difícil evitar conflictos de dependencia sin anidar dependencias. Esto es fundamental para la forma en que funciona npm, y ha demostrado ser un enfoque extremadamente exitoso.

En la página de inicio de Bower :

Bower está optimizado para el front-end. Bower utiliza un árbol de dependencia plano, que requiere solo una versión para cada paquete, lo que reduce la carga de la página al mínimo.

En resumen, npm apunta a la estabilidad. Bower apunta a una carga mínima de recursos. Si extrae la estructura de dependencia, verá esto:

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

Como puede ver, instala algunas dependencias de forma recursiva. ¡La dependencia A tiene tres instancias instaladas!

Cenador:

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

Aquí verá que todas las dependencias únicas están en el mismo nivel.

Entonces, ¿por qué molestarse en usar npm?

Tal vez la dependencia B requiere una versión diferente de la dependencia A que la dependencia C. npm instala ambas versiones de esta dependencia para que funcione de todos modos, pero Bower le dará un conflicto porque no le gusta la duplicación (porque cargar el mismo recurso en una página web es muy ineficiente y costoso, también puede dar algunos errores graves). Deberá elegir manualmente la versión que desea instalar. Esto puede tener el efecto de que una de las dependencias se romperá, pero eso es algo que deberá solucionar de todos modos.

Por lo tanto, el uso común es Bower para los paquetes que desea publicar en sus páginas web (por ejemplo , tiempo de ejecución , donde evita la duplicación), y use npm para otras cosas, como pruebas, construcción, optimización, verificación, etc. (por ejemplo , tiempo de desarrollo , donde la duplicación es menos preocupante).

Actualización para npm 3:

npm 3 todavía hace las cosas de manera diferente en comparación con Bower. Instalará las dependencias globalmente, pero solo para la primera versión que encuentre. Las otras versiones se instalan en el árbol (el módulo principal, luego node_modules).

  • [nodo_módulos]
    • dep A v1.0
    • dep B v1.0
      • dep A v1.0 (usa la versión raíz)
    • dep C v1.0
      • dep A v2.0 (esta versión es diferente de la versión raíz, por lo que será una instalación anidada)

Para obtener más información, sugiero leer los documentos de npm 3

Justus Romijn
fuente
44
Es casi un cliché ahora que "el desarrollo de software se trata de compensaciones". Es un buen ejemplo. Uno debe elegir una mayor estabilidad npm o una carga de recursos mínima con bower.
jfmercer
66
@Shrek Estoy afirmando implícitamente que en realidad puedes usar ambos. Tienen diferentes propósitos, como afirmo en el párrafo final. No es una compensación en mis ojos.
Justus Romijn
Ahh, veo que te he entendido mal. O no leí con suficiente atención. Gracias por la aclaración. :-) Es bueno que ambos puedan usarse sin una compensación.
jfmercer
44
@AlexAngas He agregado una actualización para npm3. Todavía tiene algunas diferencias importantes en comparación con Bower. npm probablemente siempre admitirá múltiples versiones de dependencias, mientras que Bower no.
Justus Romijn
npm 3 acercándose a
bower
269

TL; DR: La mayor diferencia en el uso diario no son las dependencias anidadas ... es la diferencia entre módulos y globales.

Creo que los carteles anteriores han cubierto bien algunas de las distinciones básicas. (El uso de npm de dependencias anidadas es de hecho muy útil para administrar aplicaciones grandes y complejas, aunque no creo que sea la distinción más importante).

Sin embargo, me sorprende que nadie haya explicado explícitamente una de las distinciones más fundamentales entre Bower y npm. Si lee las respuestas anteriores, verá la palabra 'módulos' utilizada a menudo en el contexto de npm. Pero se menciona casualmente, como si pudiera ser una diferencia de sintaxis.

Pero esta distinción de módulos vs. globales (o módulos vs. 'scripts') es posiblemente la diferencia más importante entre Bower y npm. El enfoque npm de poner todo en módulos requiere que cambie la forma en que escribe Javascript para el navegador, casi seguramente para mejor.

El enfoque de Bower: recursos globales, como <script>etiquetas

En la raíz, Bower se trata de cargar archivos de script simples. Independientemente de lo que contengan esos archivos de script, Bower los cargará. Lo que básicamente significa que Bower es como incluir todas sus secuencias de comandos en los viejos <script>en <head>su HTML.

Entonces, el mismo enfoque básico al que estás acostumbrado, pero obtienes algunas buenas comodidades de automatización:

  • Solía ​​necesitar incluir dependencias JS en el repositorio de su proyecto (durante el desarrollo) u obtenerlas a través de CDN. Ahora, puede omitir ese peso de descarga adicional en el repositorio, y alguien puede hacer un rápido bower instally tener instantáneamente lo que necesita, localmente.
  • Si una dependencia de Bower especifica sus propias dependencias bower.json, también se descargarán para usted.

Pero más allá de eso, Bower no cambia la forma en que escribimos JavaScript . Nada de lo que pasa dentro de los archivos cargados por Bower debe cambiar en absoluto. En particular, esto significa que los recursos proporcionados en los scripts cargados por Bower (generalmente, pero no siempre) se definirán como variables globales , disponibles desde cualquier parte del contexto de ejecución del navegador.

El enfoque npm: módulos JS comunes, inyección explícita de dependencias

Todo el código en Node land (y, por lo tanto, todo el código cargado a través de npm) está estructurado como módulos (específicamente, como una implementación del formato de módulo CommonJS , o ahora, como un módulo ES6). Entonces, si usa NPM para manejar las dependencias del lado del navegador (a través de Browserify o alguna otra cosa que haga el mismo trabajo), estructurará su código de la misma manera que Node.

Las personas más inteligentes que yo han abordado la pregunta "¿Por qué módulos?", Pero aquí hay un resumen de la cápsula:

  • Cualquier cosa dentro de un módulo tiene un espacio de nombres efectivo , lo que significa que ya no es una variable global, y no puede hacer referencia accidentalmente sin tener la intención de hacerlo.
  • Cualquier cosa dentro de un módulo debe inyectarse intencionalmente en un contexto particular (generalmente otro módulo) para poder usarlo
  • Esto significa que puede tener múltiples versiones de la misma dependencia externa (lodash, digamos) en varias partes de su aplicación, y no colisionarán / entrarán en conflicto. (Esto sucede sorprendentemente a menudo, porque su propio código quiere usar una versión de una dependencia, pero una de sus dependencias externas especifica otra que está en conflicto. O tiene dos dependencias externas que quieren una versión diferente).
  • Debido a que todas las dependencias se inyectan manualmente en un módulo en particular, es muy fácil razonar sobre ellas. Usted sabe a ciencia cierta: "El único código que debo tener en cuenta al trabajar en esto es lo que he elegido inyectar aquí" .
  • Debido a que incluso el contenido de los módulos inyectados está encapsulado detrás de la variable a la que lo asigna, y todo el código se ejecuta dentro de un alcance limitado, las sorpresas y las colisiones se vuelven muy improbables. Es mucho, mucho menos probable que algo de una de sus dependencias redefina accidentalmente una variable global sin que se dé cuenta, o que lo haga. ( Puede suceder, pero por lo general tiene que hacer todo lo posible para hacerlo, con algo como window.variable. El único accidente que aún suele ocurrir es la asignación this.variable, sin darse cuenta de que thisrealmente está windowen el contexto actual).
  • Cuando desea probar un módulo individual, puede saber muy fácilmente: ¿exactamente qué más (dependencias) están afectando el código que se ejecuta dentro del módulo? Y, como está inyectando todo explícitamente, puede burlarse fácilmente de esas dependencias.

Para mí, el uso de módulos para código de front-end se reduce a: trabajar en un contexto mucho más estrecho que es más fácil de razonar y probar, y tener una mayor certeza sobre lo que está sucediendo.


Solo lleva unos 30 segundos aprender a usar la sintaxis del módulo CommonJS / Node. Dentro de un archivo JS dado, que va a ser un módulo, primero declara cualquier dependencia externa que desee usar, como esta:

var React = require('react');

Dentro del archivo / módulo, haces lo que normalmente harías y creas algún objeto o función que querrás exponer a usuarios externos, llamándolo tal vez myModule.

Al final de un archivo, exporta lo que quiera compartir con el mundo, así:

module.exports = myModule;

Luego, para usar un flujo de trabajo basado en CommonJS en el navegador, usará herramientas como Browserify para capturar todos esos archivos de módulos individuales, encapsular sus contenidos en tiempo de ejecución e inyectarlos entre sí según sea necesario.

Y, dado que los módulos ES6 (que probablemente transpilarás a ES5 con Babel o similar) están ganando una gran aceptación y funcionan tanto en el navegador como en el Nodo 4.0, también debemos mencionar una buena descripción general de ellos.

Más sobre patrones para trabajar con módulos en este mazo .


EDITAR (febrero de 2017): el hilo de Facebook es un reemplazo / suplemento potencial muy importante para npm en estos días: gestión de paquetes rápida, determinista y fuera de línea que se basa en lo que npm le brinda. Vale la pena echarle un vistazo a cualquier proyecto JS, especialmente porque es muy fácil cambiarlo de entrada / salida.


EDITAR (mayo de 2019) "Bower finalmente ha quedado en desuso . Fin de la historia". (h / t: @DanDascalescu, a continuación, para un resumen resumido).

Y, mientras Yarn todavía está activo , gran parte del impulso cambió a npm una vez que adoptó algunas de las características clave de Yarn.

XML
fuente
13
Me alegro de que esta respuesta estuviera aquí, las otras respuestas populares no mencionan este detalle. npm te obliga a escribir código modular.
Juan Mendes
Lo siento, de una gente a la que le importa muy poco todo el fuzzing en las parlands de JavaScript, pero sucede que dirige un negocio que hace uso de una pequeña aplicación web. Recientemente me vi obligado a probar npm, desde el uso de Bower con el kit de herramientas que usamos para desarrollar la maldita web. Puedo decirte que la mayor diferencia es el tiempo de espera, npm lleva años. Recuerde que está compilando dibujos animados xkcd con los muchachos jugando peleas con espadas gritando 'compilando' a su jefe; eso es más o menos lo que npm agregó a Bower.
Pedro Rodrigues
129

Actualización 2017-Oct

Bower finalmente ha quedado en desuso . Fin de la historia.

Respuesta anterior

De Mattias Petter Johansson, desarrollador de JavaScript en Spotify :

En casi todos los casos, es más apropiado usar Browserify y npm sobre Bower. Es simplemente una mejor solución de empaque para aplicaciones front-end que Bower. En Spotify, usamos npm para empaquetar módulos web completos (html, css, js) y funciona muy bien.

Bower se marca a sí mismo como el administrador de paquetes para la web. Sería increíble si esto fuera cierto: un administrador de paquetes que mejorara mi vida como desarrollador front-end sería increíble. El problema es que Bower no ofrece herramientas especializadas para este propósito. No ofrece herramientas que conozco que npm no tiene, y especialmente ninguna que sea específicamente útil para desarrolladores front-end. Simplemente no hay beneficio para un desarrollador front-end para usar Bower sobre npm.

Deberíamos dejar de usar Bower y consolidarnos alrededor de npm. Afortunadamente, eso es lo que está sucediendo :

Recuento de módulos: bower vs. npm

Con browserify o webpack, se vuelve súper fácil concatenar todos sus módulos en grandes archivos minificados, lo que es increíble para el rendimiento, especialmente para dispositivos móviles. No es así con Bower, que requerirá mucho más trabajo para obtener el mismo efecto.

npm también le ofrece la posibilidad de usar múltiples versiones de módulos simultáneamente. Si no ha realizado mucho desarrollo de aplicaciones, esto inicialmente puede parecerle algo malo, pero una vez que haya pasado por algunos episodios del Infierno de la dependencia, se dará cuenta de que tener la capacidad de tener múltiples versiones de un módulo es bastante maldito. Gran característica. Tenga en cuenta que npm incluye una herramienta de deduplicación muy útil que se asegura automáticamente de que solo use dos versiones de un módulo si realmente tiene que hacerlo; si dos módulos pueden usar la misma versión de un módulo, lo harán. Pero si no pueden , tienes una salida muy útil.

(Tenga en cuenta que Webpack y el paquete acumulativo se consideran ampliamente mejores que Browserify a partir de agosto de 2016).

Dan Dascalescu
fuente
77
<sarcasm> Tenga en cuenta que incluso el proyecto npm 'hello world' necesita más de 300 módulos para ejecutarse ... </sarcasm>: O
Mariusz Jamro
1
No estoy de acuerdo con que los "grandes archivos minificados" sean "impresionantes para el rendimiento, especialmente para dispositivos móviles". Todo lo contrario: el ancho de banda restringido requiere archivos pequeños, cargados a pedido.
Michael Franzl
No muy buen consejo. La mayoría de los paquetes npm son solo backend de nodejs. Si no está utilizando JavaScript en el backend, o no tiene un sistema de módulos, la cantidad de paquetes es irrelevante porque Bower satisfará sus necesidades mucho mejor
Gerardo Grignoli
44
@GerardoGrignoli: Bower está saliendo .
Dan Dascalescu
45

Bower mantiene una única versión de módulos, solo trata de ayudarlo a seleccionar el correcto / mejor para usted.

Gestión de dependencia de Javascript: npm vs bower vs volo?

NPM es mejor para módulos de nodo porque hay un sistema de módulos y usted está trabajando localmente. Bower es bueno para el navegador porque actualmente solo existe el alcance global, y desea ser muy selectivo sobre la versión con la que trabaja.

Sagivf
fuente
44
Creo que Sindre menciona eso cuando habla de dependencia anidada.
Juegos Brainiac
55
@GamesBrainiac tu correcto, solo pensé que lo pondría en mis propias palabras.
Sagivf
1
@Sagivf Estas NO son sus propias palabras, a menos que usted también sea el que proporcionó la respuesta original aquí
dayuloli
44
@Sagivf No hay nada de malo en copiar ** partes relevantes de las respuestas de otros si no proporcionan una respuesta aquí ellos mismos. Me molestó un poco que dijeras "solo pensé que lo pondría en mis propias palabras". El crédito debe ir a donde se debe.
dayuloli
2
No sé por qué ustedes escogieron tanto esta respuesta. De hecho, hay nueva información / perspectiva en esta respuesta para mí.
Calvin
33

Mi equipo se mudó de Bower y migró a npm porque:

  • El uso programático fue doloroso
  • La interfaz de Bower siguió cambiando
  • Algunas características, como la abreviatura de la URL, están completamente rotas
  • Usar tanto Bower como npm en el mismo proyecto es doloroso
  • Mantener el campo de la versión bower.json sincronizado con las etiquetas git es doloroso
  • Control de fuente! = Gestión de paquetes
  • El soporte de CommonJS no es sencillo

Para obtener más detalles, consulte "Por qué mi equipo usa npm en lugar de bower" .

Nick Heiner
fuente
17

Encontré esta útil explicación en http://ng-learn.org/2013/11/Bower-vs-npm/

Por un lado, npm se creó para instalar módulos utilizados en un entorno node.js, o herramientas de desarrollo creadas con node.js como Karma, lint, minifiers, etc. npm puede instalar módulos localmente en un proyecto (por defecto en node_modules) o globalmente para ser utilizados por múltiples proyectos. En proyectos grandes, la forma de especificar dependencias es creando un archivo llamado package.json que contiene una lista de dependencias. Npm reconoce esa lista cuando ejecuta npm install, que luego las descarga e instala por usted.

Por otro lado, Bower fue creado para administrar sus dependencias frontend. Bibliotecas como jQuery, AngularJS, subrayado, etc. Similar a npm, tiene un archivo en el que puede especificar una lista de dependencias llamada bower.json. En este caso, sus dependencias frontend se instalan ejecutando bower install, que por defecto las instala en una carpeta llamada bower_components.

Como puede ver, aunque realizan una tarea similar, están dirigidos a un conjunto muy diferente de bibliotecas.

Henry Neo
fuente
1
Con la llegada de npm dedupe, esto está un poco desactualizado. Ver la respuesta de Mattias .
Dan Dascalescu
7

Para muchas personas que trabajan con node.js, una de las principales ventajas de bower es la gestión de dependencias que no son javascript en absoluto. Si están trabajando con lenguajes que compilan a javascript, npm puede usarse para administrar algunas de sus dependencias. sin embargo, no todas sus dependencias serán módulos node.js. Algunos de los que compilan en JavaScript pueden tener una extraña manipulación específica del lenguaje fuente que hace que pasarlos compilados a JavaScript sea una opción poco elegante cuando los usuarios esperan el código fuente.

No todo en un paquete npm debe ser JavaScript orientado al usuario, pero para los paquetes de la biblioteca npm, al menos algunos de ellos deberían serlo.

jessopher
fuente
Esta publicación de blog de npmjs dice "Su paquete puede contener cualquier cosa, ya sea ES6, JS del lado del cliente, o incluso HTML y CSS. Estas son cosas que naturalmente aparecen junto con JavaScript, así que póngalos ahí".
Dan Dascalescu
1
Hay una diferencia entre puede contener y debe incluir . Por supuesto, pueden contener cualquier cosa, pero en general, deben incluir algún tipo de interfaz con commonJS. Es el 'administrador de paquetes de nodos' después de todo. La parte sobre Estas son cosas que naturalmente aparecen junto con Javascript es importante. Hay muchas cosas que están tangencialmente relacionadas con JavaScript que, naturalmente, no aparecen junto a él.
jessopher