node mac last instalar node.js npm

node.js - mac - npm version



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

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

EDIT también agregó peerDependencies , que están estrechamente relacionadas y podrían causar confusión.


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


Cuando intente distribuir un paquete npm, debe evitar el uso de dependencies . En su lugar, debe considerar agregarlo a peerDependencies o eliminarlo de las dependencies .


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

Si alguien está planeando descargar y usar su módulo en su programa, entonces probablemente no quieran o necesiten descargar y crear la prueba externa o el marco de documentación que utiliza. En este caso, es mejor enumerar estos elementos adicionales en un hash devDependencies.


Me gustaría añadir a la respuesta mi opinión sobre estas explicaciones de dependencias.

  • dependencies se usan para el uso directo en su base de código, cosas que generalmente terminan en el código de producción o trozos 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, paquete web)

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

npm install "$package" --save-dev

Cuando ejecute npm install , instalará devDependencies y dependencies . Para evitar instalar devDependencies ejecute:

npm install --production


Resumen de las diferencias de comportamiento importantes:

  • dependencies se instalan tanto en:

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

    • también se instala en npm install en un directorio que contiene package.json , a menos que pase la marca --production (suba la respuesta de Gayan Charith ).
    • no está instalado en npm install "$package" en cualquier otro directorio, a menos que le dé la opción --dev .
    • no se instalan transitivamente.
  • peerDependencies

    • antes de 3.0: siempre se instalan si faltan, y genera un error si diferentes dependencias usarían versiones incompatibles de la dependencia.
    • se espera que comience en 3.0 (no probado): dé una advertencia si falta en la npm install , y tendrá que resolver la dependencia manualmente. Cuando se ejecuta, si falta la dependencia, aparece un error (mencionado por @nextgentech )
  • 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 tampoco lo haría A.

    • devDependencies no se instalan 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í:

Dependencias

se requieren dependencies 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 ), vaya a su raíz que contiene package.json y ejecute:

npm install

Ya que tiene la fuente real, está claro que desea desarrollarla, por lo que, de manera predeterminada, ambas dependencies (ya que, por supuesto, deben ejecutarse para desarrollar) y devDependency dependencias de dependencia de devDependency también están instaladas.

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

npm install "$package"

En ese caso, normalmente no desea las dependencias de desarrollo, por lo que solo obtiene lo que se necesita para usar el paquete: dependencies .

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

npm install "$package" --dev

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

dependencias peer

(Probado antes de 3.0)

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

Con las dependencias regulares, puede tener varias versiones de la dependencia: simplemente se instala dentro de los node_modules de node_modules de la dependencia.

Por ejemplo, si dependency1 y dependency2 dependen de dependency3 en diferentes versiones, 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:

  • los complementos son requeridos por el host
  • Los complementos ofrecen una interfaz estándar que el host 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 dependency1 y dependency2 peer dependen de dependency3 , el árbol del proyecto se verá así:

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

Esto sucede aunque nunca mencione dependency3 en su archivo package.json .

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 Grunt como https://github.com/gruntjs/grunt-contrib-uglify , verá que:

  • grunt es una peerDependency
  • el único require(''grunt'') está bajo tests/ : no es realmente utilizado por el programa.

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

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

Manual

Creo que la documentación responde a la pregunta bastante bien, quizás no esté lo suficientemente familiarizado con los administradores de nodos / otros paquetes. Probablemente solo lo entiendo porque sé un poco sobre Ruby bundler.

La línea clave es:

Estas cosas se instalarán cuando se realicen 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 más información sobre el tema.

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

Default: false Type: Boolean Install dev-dependencies along with packages.


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


Una explicación simple que lo hizo más claro para mí es:

Cuando implemente su aplicación, los módulos en las dependencias deben instalarse o su aplicación no funcionará. Los módulos en devDependencies no necesitan instalarse en el servidor de producción ya que no está desarrollando en esa máquina. link


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

Lo que necesitan los [ complementos ] es una forma de expresar estas "dependencias" entre los complementos y su paquete 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 dependencia de compañeros.

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

peerDependencies son para complementos, bibliotecas que requieren una biblioteca "host" para realizar su función, pero pueden haberse escrito antes de que se lanzara la última versión del host.

Es decir, si escribo PluginX v1 para HostLibraryX v3 y me alejo, no hay garantía de que PluginX v1 funcione cuando se HostLibraryX v4 (o incluso HostLibraryX v3.0.1 ).

... pero el plugin no depende del host ...

Desde el punto de vista del complemento, solo agrega funciones a la biblioteca del host. Realmente no "necesito" el host para agregar 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 inofensivamente.

Esto significa que las dependencies no son realmente el concepto correcto para los complementos.

Lo que es peor, si mi host fuera tratado como una dependencia, terminaríamos en esta situación que menciona la misma publicación del blog (editada un poco para usar el host y el complemento creados de esta respuesta):

Pero ahora, [si tratamos la versión contemporánea de HostLibraryX como una dependencia para PluginX,] ejecutar resultados de npm install en el gráfico de dependencia inesperado de

├── [email protected] └─┬ [email protected] └── [email protected]

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

... y el anfitrión obviamente no depende del complemento ...

... ese es el punto de los complementos. Ahora, si el anfitrión fue lo suficientemente bueno como para incluir información de dependencia para todos sus complementos, eso resolvería el problema, pero también introduciría un nuevo problema cultural : ¡la administración de complementos!

El punto central de los complementos es que pueden emparejarse de forma anónima. En un mundo perfecto, hacer que el anfitrión los administre a todos sería limpio y ordenado, pero no vamos a necesitar bibliotecas y gatos.

Si no somos jerárquicamente dependientes, tal vez somos compañeros intradependientes ...

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

... pero esto no es una relación automatizable

Si soy PluginX v1 y espero un par de (es decir, tengo una dependencia de HostLibraryX v3 ) de HostLibraryX v3 , lo diré. Si se actualizó automáticamente a la última HostLibraryX v4 (tenga en cuenta que es la versión 4 ) Y tiene instalado el Plugin v1 , debe saberlo, ¿verdad?

npm no puede manejar esta situación por mí

"¡Eh, veo que estás usando PluginX v1 ! Estoy degradando automáticamente HostLibraryX de v4 a v3, ¿kk?"

... o ...

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

¿Qué tal no, npm ?!

Así que npm no lo hace. Le alerta sobre la situación y le permite averiguar si HostLibraryX v4 es un compañero adecuado para Plugin v1 .

Coda

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

Un consejo: los requisitos de dependencia de los compañeros, a diferencia de los de las dependencias regulares, deben ser indulgentes. No debe bloquear las dependencias de sus compañeros en versiones específicas de parches. 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 perezosos y no pasaron el tiempo calculando la versión mínima real de Chai que son. compatible con.


dependencias
Dependencias que su proyecto necesita para ejecutar, como una biblioteca que proporciona funciones a las que 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 algunas funciones lodash.

Dependencias
Dependencias que solo necesita durante el desarrollo o la liberación, como compiladores que toman su código y lo compilan en javascript, marcos de prueba o generadores de documentación.
No se instalan de forma transitoria (si A depende de B dev-depende de C, npm install en A solo instalará B).
Ejemplo: grunt: tu proyecto usa grunt para construirse.

dependencias peer
Dependencias en las que su proyecto se enlaza 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 del proyecto al que se conecte. Por lo tanto, si crea un complemento C que agrega funcionalidad a la biblioteca B, entonces alguien que realice un proyecto A deberá tener una dependencia en B si tiene una dependencia en C.
No están instalados (a menos que npm <3), solo se comprueban.
Ejemplo: grunt: su proyecto agrega funcionalidad a grunt y solo se puede usar en proyectos que usan grunt.

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/npm/blob/master/doc/files/package.json.md#devdependencies