¿Cuál es la diferencia entre dependencias, devDependencies y peerDependencies en el archivo npm package.json?

2030

Esta documentación responde muy mal a mi pregunta. No entendí esas explicaciones. ¿Alguien puede decir en palabras más simples? ¿Quizás con ejemplos si es difícil elegir palabras simples?

EDIT también agregó peerDependencies, que está estrechamente relacionado y puede causar confusión.

Vitalii Korsakov
fuente
48
Tenga en cuenta que también hay optionalDependenciesahora.
Aidan Feldman
118
@AidanFeldman "OpcionalDependencias" es mi oxímoron del día
Nick Bull
1
La documentación de npm dice: "dependencias": paquetes requeridos por su aplicación en producción. "devDependencies": paquetes que solo son necesarios para el desarrollo y las pruebas locales. ver enlace: docs.npmjs.com/…
Deke

Respuestas:

2367

Resumen de importantes diferencias de comportamiento:

  • dependencies están instalados en ambos:

    • npm install de un directorio que contiene package.json
    • npm install $package en cualquier otro directorio
  • devDependencies son:

    • también instalado en npm installun directorio que contiene package.json, a menos que pase la --productionbandera (vaya a votar la respuesta de Gayan Charith ).
    • no está instalado en npm install "$package"ningún otro directorio, a menos que le dé la --devopción.
    • no están instalados transitivamente
  • peerDependencies:

    • antes de 3.0: siempre se instalan si faltan y generan un error si diferentes dependencias utilizarían múltiples versiones incompatibles de la dependencia.
    • se espera que comience en 3.0 (no probado): avise si falta npm install, y debe resolver la dependencia usted mismo manualmente. Cuando se ejecuta, si falta la dependencia, aparece un error (mencionado por @nextgentech )
  • Transitividad (mencionado por Ben Hutchison ):

    • dependencies se instalan transitivamente: si A requiere B y B requiere C, entonces C se instala, de lo contrario, B no podría funcionar, y tampoco A.

    • devDependenciesno está instalado transitivamente Por ejemplo, no necesitamos probar B para probar A, por lo que las dependencias de prueba de B pueden omitirse.

Opciones relacionadas no discutidas aquí:

devDependencies

dependenciesson necesarios para ejecutar, devDependenciessolo para desarrollar, por ejemplo: pruebas unitarias, CoffeeScript a JavaScript, recopilación, minificación, ...

Si va a desarrollar un paquete, descárguelo (por ejemplo, a través de git clone), vaya a su raíz que contiene package.jsony ejecute:

npm install

Como tiene la fuente real, está claro que desea desarrollarla, por lo que, de manera predeterminada, tanto dependencies(como debe, por supuesto, ejecutar para desarrollar) como las devDependencydependencias también están instaladas.

Sin embargo, si solo es un usuario final que solo desea instalar un paquete para usarlo, lo hará desde cualquier directorio:

npm install "$package"

En ese caso, normalmente no quieren las dependencias de desarrollo, por lo que acaba de obtener lo que se necesita para usar el paquete: dependencies.

Si realmente desea instalar paquetes de desarrollo en ese caso, puede establecer la devopción de configuración true, posiblemente desde la línea de comandos como:

npm install "$package" --dev

La opción es falsepor defecto ya que este es un caso mucho menos común.

Dependencias

(Probado antes de 3.0)

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

Con dependencias regulares, puede tener múltiples versiones de la dependencia: simplemente se instala dentro node_modulesde la dependencia.

Por ejemplo, si dependency1y dependency2ambos dependen de dependency3versiones diferentes, el árbol del proyecto se verá así:

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

Sin embargo, los complementos son paquetes que normalmente no requieren el otro paquete, que se denomina host en este contexto. En lugar:

  • el host requiere complementos
  • los complementos ofrecen una interfaz estándar que el anfitrión espera encontrar
  • solo el host será llamado directamente por el usuario, por lo que debe haber una única versión del mismo.

Por ejemplo, si dependency1y por dependency2pares dependen dependency3, el árbol del proyecto se verá así:

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

Esto sucede aunque nunca lo mencione dependency3en su package.jsonarchivo.

Creo que esta es una instancia del patrón de diseño de Inversión de control .

Un ejemplo prototípico de dependencias entre pares es Grunt, el host y sus complementos.

Por ejemplo, en un complemento de Grunt como https://github.com/gruntjs/grunt-contrib-uglify , verá que:

  • grunt es un peer-dependency
  • el único require('grunt')está debajo tests/: el programa no lo utiliza realmente.

Luego, cuando el usuario usará un complemento, implícitamente requerirá el complemento al Gruntfileagregar una grunt.loadNpmTasks('grunt-contrib-uglify')línea, pero es gruntque el usuario llamará directamente.

Esto no funcionaría si cada complemento requiriera una versión diferente de Grunt.

Manual

Creo que la documentación responde bastante bien a la pregunta, tal vez no esté tan familiarizado con los nodos / otros gestores de paquetes. Probablemente solo lo entiendo porque sé un poco sobre el paquete Ruby.

La línea clave es:

Estas cosas se instalarán al hacer el enlace npm o la instalación npm desde la raíz de un paquete y se pueden administrar como cualquier otro parámetro de configuración npm. Consulte npm-config (7) para obtener más información sobre el tema.

Y luego en npm-config (7) encuentra dev:

Default: false
Type: Boolean

Install dev-dependencies along with packages.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
fuente
55
Ah Veo que he entendido mal. Su respuesta se lee como si fuera npm install packageun comando que usaría para instalar todos los paquetes que no son dependencias del desarrollador, en lugar de lo que ahora creo que quiso decir, que era 'instalar el paquete llamado [paquete]', que fue como pensé que funcionaba antes de leer esto Si fuera usted, editaría para decir [nombre-paquete], lo que muestra claramente que lo que quiere decir es 'insertar nombre-aquí'.
Tom W
184
¡Esto es genial! Nunca me di cuenta, pero esta respuesta me ha enseñado que la diferencia de dependencias vs devDependencies solo es aplicable si vas a publicar un paquete npm. Si solo está trabajando en una aplicación o sitio, no debería importar demasiado. ¡Gracias!
jedd.ahyoung
3
Esta publicación debe actualizarse para reflejar el cambio de peerDependenciescomportamiento en el próximo npm @ 3. De blog.npmjs.org/post/110924823920/npm-weekly-5 : "Ya no descargaremos automáticamente la dependencia de pares. En su lugar, le avisaremos si la dependencia de pares no está instalada. Esto requiere que usted para resolver conflictos de dependencia entre usted mismo, manualmente, pero a la larga esto debería hacer que sea menos probable que termine en un lugar complicado con las dependencias de sus paquetes ".
nextgentech
8
Además, devDependencies no se instalan transitivamente por paquetes dependientes. Ejemplo: el paquete A depende del paquete B. El paquete B depende del paquete C, y B también depende del paquete D. Si se ejecuta npm installdesde el paquete A, obtendrá B y C pero no D.
Ben Hutchison
99
Es importante destacar que devDependenciesno se instalan cuando NODE_ENVestá configurado en production.
Augusto Franzoia
491

Si no desea instalar devDependencies, puede usar npm install --production

Gayan Charith
fuente
1
npm install --save es para la dependencia del software?
Vamsi Pavan Mahesh
19
npm install instalará todas las dependencias. --save flag se usa cuando desea agregar el módulo específico a package.json también. por ejemplo: - npm install uglify --save instalará uglify en su carpeta de proyecto y agregará uglify al proyecto, archivo package.json.
Gayan Charith
66
Y como estamos hablando de devDependencies, puede usar --save-dev para guardar el nuevo módulo como devDependency. Ejemplo: npm install uglify --save-dev
Mykaelos
99
A partir de npm 5, la --saveopción ya no es necesaria. Si hace "npm install my-package", agregará my-package como una dependencia en su package.jsonarchivo.
Martin Carel
solo npm install
sultan aslam
116

Como ejemplo, mocha normalmente sería una dependencia de desarrollo, ya que las pruebas no son necesarias en la producción, mientras que express sería una dependencia.

Dan Kohn
fuente
44
Me inclinaría por poner las pruebas como una dependencia, ya que es posible que desee realizar autocomprobaciones antes de iniciar el servidor de producción
47
En cambio, recomendaría usar un servicio de integración continua como Hudson o CircleCI que ejecuta sus pruebas y luego se implementa en producción si pasan.
Dan Kohn
1
Todavía puede ser relevante probar el servidor real porque el servidor CI puede diferir de alguna manera del servidor prod, y esta diferencia puede, por ejemplo, evitar que la aplicación se inicie ...
Nicole
2
@Nicole ¿por qué haría que su servidor provisional no sea idéntico en configuración a su producto?
Lucas
1
Por otra parte, agregar dependencias de prueba como dependencias regulares introduce un montón de bibliotecas adicionales, cada una de las cuales puede fallar de alguna manera. Me inclinaría (¡juego de palabras!) Hacia servidores de producción livianos con el menor código posible. ¡Recuerde, el mejor código es sin código!
Stijn de Witt
69

dependencias
Dependencias que su proyecto necesita ejecutar, como una biblioteca que proporciona funciones a las que llama desde su código.
Se instalan transitivamente (si A depende de B depende de C, npm install en A instalará B y C).
Ejemplo: lodash: su proyecto llama a algunas funciones lodash.

devDependencies
Dependencias que solo necesita durante el desarrollo o el lanzamiento, como compiladores que toman su código y lo compilan en javascript, marcos de prueba o generadores de documentación.
No se instalan transitivamente (si A depende de B, dev depende de C, npm install en A solo instalará B).
Ejemplo: gruñido: su proyecto utiliza gruñido para construirse.

peerDependencies
Dependencias a las que su proyecto se conecta o modifica en el proyecto principal, generalmente un complemento para alguna otra biblioteca o herramienta. Solo pretende ser una verificación, asegurándose de que el proyecto principal (proyecto que dependerá de su proyecto) tenga una dependencia en el proyecto al que se conecta. Entonces, si crea un complemento C que agrega funcionalidad a la biblioteca B, entonces alguien que realice un proyecto A necesitará tener una dependencia de B si tiene una dependencia de C.
No están instalados (a menos que npm <3), solo sean comprobado
Ejemplo: gruñido: su proyecto agrega funcionalidad a gruñido y solo se puede usar en proyectos que usan gruñido.

Esta documentación explica muy bien las dependencias entre pares: https://nodejs.org/en/blog/npm/peer-dependencies/

Además, la documentación de npm se ha mejorado con el tiempo y ahora tiene mejores explicaciones de los diferentes tipos de dependencias: https://github.com/npm/cli/blob/latest/doc/files/package.json.md#devdependencies

qwertzguy
fuente
63

Para guardar un paquete en package.json como dependencias de desarrollo:

npm install "$package" --save-dev

Cuando lo ejecutes npm install, instalará ambos devDependenciesy dependencies. Para evitar la instalación, devDependenciesejecute:

npm install --production
Mohammed Safeer
fuente
3
también puedes usar: npm i -S
Maysara Alhindi
36

Hay algunos módulos y paquetes solo necesarios para el desarrollo, que no son necesarios en la producción. Como lo dice en la documentación :

Si alguien planea descargar y usar su módulo en su programa, entonces probablemente no quiera o necesite descargar y construir la prueba externa o el marco de documentación que usa. En este caso, es mejor enumerar estos elementos adicionales en un hash devDependencies.

Lámparas de color ambar
fuente
¿Qué sucede si solo está ejecutando el archivo bundle.js en producción? ¿realmente necesitas esas dependencias?
RegarBoy
Si está ejecutando bundle.js en el servidor, está haciendo un paquete web del lado del servidor o algo así ... Compruebe si ese es el caso porque generalmente no es así y realmente toma mucho trabajo hacer que funcione correctamente (I sé porque hice eso). Sospecho que su bundle.js solo se sirve en los navegadores y contiene el código del lado del cliente.
Stijn de Witt
16

Una explicación simple que me dejó más claro es:

Cuando implementa su aplicación, los módulos en dependencias deben instalarse o su aplicación no funcionará. No es necesario instalar módulos en devDependencies en el servidor de producción ya que no está desarrollando en esa máquina. enlace

Jyoti Duhan
fuente
2
Entonces, si estamos haciendo un sitio web y en la versión prod vendor.js, todas las bibliotecas se incluirán, todos nuestros departamentos deberían ser deps si el código compilado se confirma en el repositorio. Y debe confirmarse, ya que de lo contrario es extraño que tenga que compilar el módulo, no solo instalarlo (y las pruebas también están en algún lugar aquí, ya que cualquier cambio en los submódulos puede conducir a una regresión) ...
Qwertiy
Impresionante respuesta, pero hay una pregunta? ¿Es posible Webpack construir un paquete dañado? Supongo que los paquetes devDependencies no funcionarán en la versión del producto, webpack -pquiero decir. por favor responde mi pregunta.
AmerllicA
Si hay algún problema durante la compilación de producción, su proceso de implementación debe diseñarse de manera que muestre un error en el momento de la compilación y no empuje el código dañado a la producción (por ejemplo, puede probar Jenkins). De todos modos, no se requiere que las dependencias de desarrollo se instalen en el servidor de producción.
Jyoti Duhan
¿Y las dependencias entre pares?
dev27
13

Me gustaría agregar a la respuesta mi opinión sobre estas explicaciones de dependencias

  • dependencies se usan para uso directo en su base de código, cosas que generalmente terminan en el código de producción o fragmentos de código
  • devDependencies se utilizan para el proceso de compilación, herramientas que lo ayudan a administrar cómo terminará el código final, módulos de prueba de terceros (por ejemplo, material webpack)
Sîrbu Nicolae-Cezar
fuente
¿Qué pasa con los activos de CSS?
Brian Zelip
8

En breve

  1. Dependencias : npm install <package> --save-prodinstala los paquetes requeridos por su aplicación en el entorno de producción.

  2. DevDependencies : npm install <package> --save-devinstala paquetes necesarios solo para desarrollo y pruebas locales

  3. Simplemente escribiendo npm installinstala todos los paquetes mencionados en package.json

así que si está trabajando en su computadora local simplemente escriba npm instally continúe :)

cherankrish
fuente
6

peerDependenciesno tenía sentido para mí hasta que leí este fragmento de una publicación de blog sobre el tema que Ciro mencionó anteriormente :

Lo que [los complementos ] necesitan es una forma de expresar estas "dependencias" entre los complementos y su paquete de host. Alguna forma de decir: "Solo trabajo cuando estoy conectado a la versión 1.2.x de mi paquete de host, así que si me instalas, asegúrate de que esté junto a un host compatible". Llamamos a esta relación una dependencia entre pares.

El complemento espera una versión específica del host ...

peerDependenciesson para complementos, bibliotecas que requieren una biblioteca "host" para realizar su función, pero pueden haberse escrito en un momento anterior al lanzamiento de la última versión del host.

Es decir, si escribo PluginX v1para HostLibraryX v3y me alejo, no hay garantía PluginX v1funcionará cuando HostLibraryX v4(o incluso HostLibraryX v3.0.1) se libera.

... pero el complemento no depende del host ...

Desde el punto de vista del complemento, solo agrega funciones a la biblioteca host. Realmente no "necesito" que el host agregue una dependencia a un complemento, y los complementos a menudo no dependen literalmente de su host. Si no tiene el host, el complemento no hace nada inofensivo.

Esto significa dependenciesque no es realmente el concepto correcto para los complementos.

Peor aún, si mi host fuera tratado como una dependencia, terminaríamos en esta situación que menciona la misma publicación del blog (editado un poco para usar el host y el complemento inventados de esta respuesta):

Pero ahora, [si tratamos la versión contemporánea de HostLibraryX como una dependencia para PluginX], la ejecución npm installda como resultado el gráfico de dependencia inesperado de

├── HostLibraryX@4.0.0
└─┬ PluginX@1.0.0
  └── HostLibraryX@3.0.0

Dejaré las sutiles fallas que provienen del complemento usando una API [HostLibraryX] diferente a la aplicación principal para su imaginación.

... y el host obviamente no depende del complemento ...

... ese es el objetivo de los complementos. Ahora, si el host fuera lo suficientemente amable como para incluir información de dependencia para todos sus complementos, eso resolvería el problema, pero eso también introduciría un gran problema cultural nuevo : ¡administración de complementos!

El objetivo de los complementos es que pueden emparejarse de forma anónima. En un mundo perfecto, hacer que el anfitrión los administre todo sería ordenado, pero no vamos a requerir bibliotecas de gatos de rebaño.

Si no somos jerárquicamente dependientes, tal vez somos pares intradependientes ...

En cambio, tenemos el concepto de ser compañeros. Ni el host ni el complemento se encuentran en el grupo de dependencia del otro. Ambos viven en el mismo nivel del gráfico de dependencia.


... pero esta no es una relación automatizable. <<< Moneyball !!!

Si soy PluginX v1y espero un par de (es decir, tengo una dependencia de par de ) HostLibraryX v3, lo diré. Si se ha actualizado automáticamente a la última HostLibraryX v4versión (tenga en cuenta que es la versión 4 ) Y se ha Plugin v1instalado, debe saberlo, ¿verdad?

npm no puede manejar esta situación por mí

"¡Oye, veo que estás usando PluginX v1! Estoy automáticamente bajando HostLibraryXde v4 a v3, ¿kk?"

... o ...

"Oye, veo que estás usando PluginX v1. Eso espera HostLibraryX v3, lo que has dejado en el polvo durante tu última actualización. ¡Para estar seguro, lo estoy desinstalando automáticamente Plugin v1! 1!

¿Qué tal no, npm?

Entonces npm no. Le alerta sobre la situación y le permite determinar si HostLibraryX v4es un par adecuado para él Plugin v1.


Coda

Una buena peerDependencyadministración de complementos hará que este concepto funcione de manera más intuitiva en la práctica. De la publicación del blog , una vez más ...

Un consejo: los requisitos de dependencia entre pares, a diferencia de los de las dependencias regulares, deben ser indulgentes. No debe bloquear sus dependencias pares a versiones de parche específicas. Sería realmente molesto si un complemento de Chai dependiera de Chai 1.4.1, mientras que otro dependiera de Chai 1.5.0, simplemente porque los autores eran flojos y no pasaban el tiempo descubriendo la versión mínima real de Chai. compatible con.

ruffin
fuente
4

Dependencias vs dependencias de desarrollo

Las dependencias de desarrollo son módulos que solo se requieren durante el desarrollo, mientras que las dependencias se requieren en tiempo de ejecución. Si está implementando su aplicación, se deben instalar las dependencias, o su aplicación simplemente no funcionará. Las bibliotecas a las que llama desde su código que permite que el programa se ejecute pueden considerarse dependencias.

Por ejemplo, reaccionar, reaccionar - dom

No es necesario instalar módulos de dependencia de desarrollo en el servidor de producción, ya que no va a desarrollar en esa máquina. Los compiladores que convierten su código a JavaScript, marcos de prueba y generadores de documentos pueden considerarse dependencias de desarrollo, ya que solo son necesarios durante el desarrollo.

Por ejemplo: ESLint, Babel, webpack

@FYI,

mod-a
  dev-dependents:
    - mod-b
  dependents:
    - mod-c

mod-d
  dev-dependents:
    - mod-e
  dependents:
    - mod-a

----

npm install mod-d

installed modules:
  - mod-d
  - mod-a
  - mod-c

----

checkout the mod-d code repository

npm install

installed modules:
  - mod-a
  - mod-c
  - mod-e

Si está publicando en npm, entonces es importante que use el indicador correcto para los módulos correctos. Si es algo que su módulo npm necesita para funcionar, utilice el indicador "--save" para guardar el módulo como una dependencia. Si es algo que su módulo no necesita para funcionar pero es necesario para la prueba, entonces use el indicador "--save-dev".

# For dependent modules
npm install dependent-module --save

# For dev-dependent modules
npm install development-module --save-dev
Selva Ganapathi
fuente
1

Cuando intente distribuir un paquete npm, debe evitar usarlo dependencies. En su lugar, debe considerar agregarlo peerDependencieso eliminarlo dependencies.

Melchia
fuente
1

Encontré una explicación simple.

Respuesta corta:

dependencias "... son aquellas que su proyecto realmente necesita para poder trabajar en la producción".

devDependencies "... son las que necesita durante el desarrollo".

peerDependencies "si desea crear y publicar su propia biblioteca para que pueda usarse como una dependencia"

Más detalles en esta publicación: https://code-trotter.com/web/dependencies-vs-devdependencies-vs-peerdependencies

usuario-necesita-ayuda
fuente