¿Cuál es la diferencia entre dependencias, devDependencies y peerDependencies en el archivo NPM package.json?
Esta documentación responde muy mal a mi pregunta. No entendí esas explicaciones. ¿Alguien puede decirlo con palabras más simples? ¿Quizás con ejemplos si es difícil elegir palabras sencillas?
También se agregó peerDependencies
, que está estrechamente relacionado y puede causar confusión.
Resumen de diferencias de comportamiento importantes:
dependencies
están instalados en ambos:npm install
de un directorio que contienepackage.json
npm install $package
en cualquier otro directorio
devDependencies
son:- también instalado en
npm install
un directorio que contienepackage.json
, a menos que pase la--production
bandera (vote la respuesta de Gayan Charith ), o si laNODE_ENV=production
variable de entorno está configurada - no está instalado
npm install "$package"
en ningún otro directorio, a menos que le dé la--dev
opción. - no se instalan transitivamente.
- también instalado en
peerDependencies
:- anteriores a 3.0: siempre se instalan si faltan y generan un error si diferentes dependencias utilizarían varias versiones incompatibles de la dependencia.
- Se espera que comience en 3.0 (no probado): envíe una advertencia si falta
npm install
y deberá resolver la dependencia usted mismo manualmente. Al ejecutar, si falta la dependencia, aparece un error (mencionado por @nextgentech ). Esto lo explica muy bien: https://flaviocopes.com/npm-peer-dependencies/ - en la versión 7, las peerDependencies se instalan automáticamente a menos que exista un conflicto de dependencia ascendente que no se pueda resolver automáticamente.
Transitividad (mencionada por Ben Hutchison ):
dependencies
se instalan de forma transitiva: si A requiere B y B requiere C, entonces C se instala; de lo contrario, B no podría funcionar y A tampoco.devDependencies
no 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 que no se analizan aquí:
bundledDependencies
que se analiza en la siguiente pregunta: Ventajas de las dependencias incluidas sobre las dependencias normales en npmoptionalDependencies
(mencionado por Aidan Feldman )
devDependencias
dependencies
se requieren para ejecutar, devDependencies
solo para desarrollar, por ejemplo: pruebas unitarias, transpilación de CoffeeScript a JavaScript, minificación, ...
Si va a desarrollar un paquete, lo descarga (por ejemplo, a través de git clone
), va a la raíz que contiene package.json
y ejecuta:
npm install
Dado que tiene la fuente real, está claro que desea desarrollarla, por lo que, de forma predeterminada, también se instalan tanto dependencies
(ya que, por supuesto, debe ejecutar para desarrollar) como las devDependency
dependencias.
Sin embargo, si sólo eres un usuario final que sólo quiere instalar un paquete para usarlo, lo harás desde cualquier directorio:
npm install "$package"
En ese caso, normalmente no deseas las dependencias de desarrollo, por lo que solo obtienes lo que necesitas para usar el paquete: dependencies
.
Si realmente desea instalar paquetes de desarrollo en ese caso, puede configurar la dev
opción de configuración en true
, posiblemente desde la línea de comando como:
npm install "$package" --dev
La opción está false
por defecto ya que este es un caso mucho menos común.
dependencias entre pares
(Probado antes de 3.0)
Fuente: https://nodejs.org/en/blog/npm/peer-dependencies/
Con las dependencias normales, puedes tener múltiples versiones de la dependencia: simplemente se instala dentro node_modules
de la dependencia.
Por ejemplo, si dependency1
y dependency2
ambos dependen dependency3
de diferentes versiones, el árbol del proyecto se verá así:
root/node_modules/
|
+- dependency1/node_modules/
| |
| +- dependency3 v1.0/
|
|
+- dependency2/node_modules/
|
+- dependency3 v2.0/
Los complementos, sin embargo, son paquetes que normalmente no requieren el otro paquete, que en este contexto se denomina host . En cambio:
- Los complementos son requeridos por el anfitrión.
- Los complementos ofrecen una interfaz estándar que el anfitrión espera encontrar.
- El usuario solo llamará directamente al host, por lo que debe haber una única versión del mismo.
Por ejemplo, si dependency1
un dependency2
par depende de dependency3
, el árbol del proyecto se verá así:
root/node_modules/
|
+- dependency1/
|
+- dependency2/
|
+- dependency3 v1.0/
Esto sucede aunque nunca lo menciones dependency3
en tu package.json
expediente.
Creo que este es un ejemplo 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ás eso:
grunt
es unpeer-dependency
- el único
require('grunt')
está debajotests/
: en realidad el programa no lo utiliza.
Luego, cuando el usuario use un complemento, implícitamente requerirá el complemento agregando Gruntfile
una grunt.loadNpmTasks('grunt-contrib-uglify')
línea, pero grunt
el usuario lo 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 simplemente no esté lo suficientemente familiarizado con los administradores de nodos/otros paquetes. Probablemente solo lo entiendo porque sé un poco sobre el paquete Ruby.
La línea clave es:
Estas cosas se instalarán al realizar npm link o npm install desde la raíz de un paquete y se pueden administrar como cualquier otro parámetro de configuración de npm. Consulte npm-config(7) para obtener más información sobre el tema.
Y luego, en npm-config(7), busque dev
:
Default: false
Type: Boolean
Install dev-dependencies along with packages.
Si no desea instalar devDependencies, puede utilizarnpm install --production
dependencias
Dependencias que su proyecto necesita para ejecutarse, como una biblioteca que proporciona funciones que usted llama desde su código.
Se instalan de forma transitiva (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 necesitas durante el desarrollo o el lanzamiento, como compiladores que toman tu código y lo compilan en javascript, marcos de prueba o generadores de documentación.
No se instalan de forma transitiva (si A depende del desarrollo B, depende de C, npm install en A instalará B solo).
Ejemplo: gruñido: su proyecto utiliza gruñido para construirse.
peerDependencies
Dependencias que su proyecto 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) dependa del 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 están comprobado.
Ejemplo: gruñido: su proyecto agrega funcionalidad a gruñido y solo puede usarse 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/docs/content/configuring-npm/package-json .md#dependenciasdev
Como ejemplo, mocha normalmente sería una dependencia dev, ya que las pruebas no son necesarias en producción, mientras que express sería una dependencia.
Para guardar un paquete en package.json como dependencias de desarrollo:
npm install "$package" --save-dev
Cuando lo ejecute npm install
, instalará tanto devDependencies
como dependencies
. Para evitar la instalación devDependencies
, ejecute:
npm install --production