Uso de npm para instalar o actualizar los paquetes requeridos como bundler para rubygems

88

Me encanta Bundler , es excelente para la gestión de dependencias. Me encanta npm , ¡instalar paquetes de nodos es fácil! Tengo una aplicación nodejs y me encantaría poder especificar las dependencias de mis aplicaciones e instalarlas / actualizarlas fácilmente donde sea que implemente mi aplicación. Esta no es una biblioteca que estoy lanzando, es una aplicación web completa.

Soy consciente del npm bundlecomando, pero parece que simplemente anula el directorio donde están instalados los paquetes.

Estoy acostumbrado a usar bundler de esta manera:

# Gemfile
gem "rails", "3.0.3"

Instala rails v3.0.3 y cualquier otra gema requerida en la máquina host solo si aún no existe

> bundle install

¿Cómo puedo lograr algo similar con npm?

Daniel Beardsley
fuente
¿No es mi respuesta lo que querías saber?
Alfred

Respuestas:

147

A partir de npm 1.0 (que ahora es lo que obtiene de forma predeterminada si sigue los pasos en el archivo README), "paquete" ya no es una cosa separada, es simplemente "cómo funciona".

Entonces:

  1. Pon un package.jsonarchivo en la raíz de tu proyecto
  2. Enumere sus departamentos en ese archivo

    { "name" : "my-project"
    , "version" : "1.0.0"
    , "dependencies" : { "express" : "1.0.0" } }
    
  3. npm install Como está llamando a esto sin argumentos, y no en modo global, simplemente instalará todos sus departamentos localmente.

  4. require("express") y se feliz.
isaacs
fuente
2
Cuando esté en producción, recomiendo encarecidamente cambiar el your_app/node_modulesdirectorio local a un enlace simbólico fuera del directorio de su aplicación. No desea tener que descargar, compilar e instalar cada dependencia cada vez que implementa.
Daniel Beardsley
Okay. ¿Qué pasa si olvido actualizar mi package.json? ¿Hay alguna forma de obligar a NPM a buscar no package.json sino paquetes que estoy usando en mi código?
Pono
4
Esto no es muy correcto. NPM instalará todas las dependencias para lo anterior my-projecten ./node_modules/my-project/node_modules. No estoy seguro de si existe una forma conveniente de instalar todas las dependencias en ./node_modules Anyone.
Daniel Beardsley
@DanielBeardsley No creo que así sea como funciona npm. Si está viendo ese comportamiento y puede reproducirlo, publique un problema en la página de npm github.
isaacs
2
De acuerdo con @DanielBeardsley. Sufro de ese comportamiento incluso con npm 1.1.70
graffic
10

Editar: esto solo se aplica a las versiones npm <1.0


Fue bastante difícil resolver esto, pero la NPM lo hace posible .

Necesitas tres componentes

  1. Un subdirectorio en su repositorio (es decir deps/)
  2. Un package.jsonarchivo en el directorio anterior que enumera las dependencias
  3. Un index.jsarchivo en el directorio anterior que requiere sus dependencias

Ejemplo

Imagina que express es tu única dependencia

deps / package.json

nota: Incremente el número de versión cada vez que modifique las dependencias

{
  "name": "myapp_dependencies",
  "version": "0.0.1",
  "engines": {
    "node": "0.4.1"
  },
  "dependencies":{
    "express": "2.0.0beta2"
  }
}

deps / index.js

export.modules = {
  express: require('express')
  //add more
}

Ahora debería poder instalar sus dependencias usando npm. Incluso podría hacer que esto sea parte de su proceso de implementación

cd deps
npm install

Luego, dentro del código de su aplicación, puede obtener acceso a su versión específica de express de esta manera:

var express = require('myapp_dependencies').express;
Daniel Beardsley
fuente
Gracias, este es el mejor método que he visto hasta ahora. Sin embargo, ¿no require('express')importaría in deps / index.js la última versión express, y no necesariamente la que instalamos? Soy un novato de nodeJS así que por favor tengan paciencia conmigo.
adamJLev
No, esa es la magia de npm install, agrega enlaces simbólicos dentro del directorio de su paquete instalado a las versiones correctas de los paquetes dependientes. Cuando se requiere su paquete de dependencias, require('express')primero verifica el directorio local y encuentra el enlace simbólico a la versión correcta de express.
Daniel Beardsley
5

Debería leer estos dos artículos del blog Isaacs (autor npm). Creo que son realmente buenos, y creo que te dirán cómo lograr tu objetivo:

  1. http://blog.izs.me/post/1675072029/10-cool-things-you-probably-didnt-realize-npm-could-do
  2. http://foohack.com/2010/08/intro-to-npm/

Creo que el enlace n. ° 1 (punto n. ° 11) explica esto:

11: agrupe todas sus dependencias en el propio paquete

Cuando usa el comando del paquete npm, npm colocará todas sus dependencias en la carpeta node_modules en su paquete. Pero no se detiene ahí.

Si desea depender de algo que no está en el registro, puede hacerlo. Solo haz esto:

npm bundle install http://github.com/whoever/whatever/tarball/master Esto instalará el contenido de ese tarball en el paquete, y luego podrá listarlo como una dependencia, y no intentará instalarlo cuando su paquete se instala.

Esto también es útil si tiene su propia bifurcación de algo y prefiere no cambiar el nombre.

De hecho, puede ejecutar casi cualquier comando npm en el paquete. Para ver lo que hay dentro, puede hacer npm bundle ls. Para eliminar algo, haga npm bundle rm thing. Y, por supuesto, puedes instalar varias versiones y activar la que quieras.

Alfredo
fuente
Esto es útil, aunque no era lo que estaba buscando. Quizás necesito agregar una aclaración. Estoy buscando una forma de instalar o actualizar automáticamente (en la máquina de destino) los paquetes de NPM de los que depende mi aplicación cada vez que la implemente. Parece que npm bundlese utiliza para recopilar todas sus dependencias en un directorio específico que no sea el predeterminado. Probablemente se me ocurrirá mi propia solución que funcione de manera similar a bundle install( bundlerpara ruby)
Daniel Beardsley
1
Solo una nota, desde la npmversión 1.0+, npm bundlese ha eliminado. En su lugar, use el npm installcomando sin nombre de paquete, leerá package.json y desplegará los paquetes requeridos.
Arthur Maltson
2

A partir de la versión 1.1.2 de Npm, hay un nuevo comando npm shrinkwrapque crea un npm-shrinkwrapped.jsonarchivo, análogo a Gemfile.lock. Es importante hacer uno para evitar que el software se pudra (consulte la justificación de Bundler ). Particularmente porque Nodejs tiene una comunidad que se mueve tan rápido.

Aunque bundle installcrea un Gemfile.lockautomáticamente, npm installno lo creará npm-shrinkwrapped.json(pero lo usará cuando exista). Por lo tanto, debe recordar usar npm shrinkwrap.

Lea una guía completa en http://blog.nodejs.org/2012/02/27/managing-node-js-dependencies-with-shrinkwrap/

Coronel Panic
fuente
2

Me parece que la solución más simple es usar un package.jsonarchivo con el privateindicador (agregado a npm el mes pasado) configurado en true. De esa manera, puedes correr npm installonpm bundle tomar las dependencias de su proyecto, pero evita que alguien publique accidentalmente su proyecto no público.

He aquí un ejemplo package.json:

{
"name": "yourProject"
,"version": "1.0.0"
,"dependencies": { "express" : ">=2.1.0" }
,"private": true
}

La ejecución npm installse instalará expressen el sistema local si aún no existe; corriendo npm publishda un error debido a la"private": true .

Usted y su equipo pueden usar la etiqueta de versión internamente para realizar un seguimiento de los cambios de dependencia a lo largo del tiempo; cada vez que cambie una dependencia, aumente la versión. Para ver qué versión ha instalado, use npm ls installed.

Trevor Burnham
fuente
Creo que no debes citar truey que solo funciona porque las cadenas son valores veraces (es decir, !!"false" === true).
Camilo Martin
1

Publica tu aplicación con npm también y enumere sus dependencias en su archivo package.json.

Cuando alguien lo utilice npmpara instalar su paquete, npmse encargará de resolver sus dependencias.

Especificaciones de paquetes: http://wiki.commonjs.org/wiki/Packages/1.0

Dan Grossman
fuente
Sí, pero esta es una aplicación web que no es de código abierto. Si tiene una idea que no implique la publicación de la aplicación, edite su respuesta o cree otra.
Daniel Beardsley
1
Luego, publique un paquete como "myapp-dependencies" que sus usuarios puedan usar npmpara instalar antes de instalar su aplicación. No creo que haya ningún otro gemequivalente para node.js.
Dan Grossman