Usando o npm para instalar ou atualizar os pacotes necessários, assim como o bundler para rubygems

88

Eu amo o Bundler , é ótimo no gerenciamento de dependências. Eu amo o npm , instalar pacotes de nó é fácil! Tenho um aplicativo nodejs e adoraria poder especificar as dependências de meus aplicativos e instalá-los / atualizá-los facilmente onde quer que eu implante meu aplicativo. Esta não é uma biblioteca que estou lançando, é um aplicativo da web completo.

Estou ciente do npm bundlecomando, mas ele simplesmente parece substituir o diretório onde os pacotes são instalados.

Estou acostumado a usar bundler desta maneira:

# Gemfile
gem "rails", "3.0.3"

Instala o rails v3.0.3 e quaisquer outras joias necessárias na máquina host apenas se ainda não existir

> bundle install

Como posso conseguir algo semelhante com o npm?

Daniel Beardsley
fonte
minha resposta não é o que você queria saber?
Alfred

Respostas:

147

A partir do npm 1.0 (que agora é o que você obtém por padrão se seguir as etapas no arquivo README), "pacote" não é mais uma coisa segregada - é apenas "como funciona".

Assim:

  1. Coloque um package.jsonarquivo na raiz do seu projeto
  2. Liste seus departamentos nesse arquivo

    { "name" : "my-project"
    , "version" : "1.0.0"
    , "dependencies" : { "express" : "1.0.0" } }
    
  3. npm install Como você está chamando isso sem args e não no modo global, ele apenas instalará todos os seus dep's localmente.

  4. require("express") e seja feliz.
isaacs
fonte
2
Quando em produção, eu recomendo altamente alterar o your_app/node_modulesdiretório local para um link simbólico fora do diretório do seu aplicativo. Você não quer ter que baixar, construir e instalar cada dependência sempre que implantar.
Daniel Beardsley
Está bem. e se eu esquecer de atualizar meu package.json? Existe alguma maneira de forçar o NPM a procurar não por package.json, mas por pacotes que estou usando em meu código?
Pono
4
isto não está correto. O NPM instalará todas as dependências acima my-projectem ./node_modules/my-project/node_modules. Não tenho certeza se existe uma maneira conveniente de fazer com que ele instale todas as dependências no ./node_modules Anyone?
Daniel Beardsley
@DanielBeardsley Não acho que seja assim que o npm funciona. Se você está vendo esse comportamento e pode reproduzi-lo, poste um problema na página npm do github.
isaacs
2
Concordo com @DanielBeardsley. Eu sofro desse comportamento mesmo com npm 1.1.70
graffic
10

Editar: Isso se aplica apenas às versões npm <1.0


Foi muito difícil descobrir isso, mas a NPM torna isso possível .

Você precisa de três componentes

  1. Um subdiretório em seu repositório (ou seja deps/)
  2. Um package.jsonarquivo no diretório acima que lista as dependências
  3. Um index.jsarquivo no diretório acima que requer suas dependências

Exemplo

Imagine que expresso é sua única dependência

deps / package.json

nota: aumente o número da versão cada vez que modificar as dependências

{
  "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
}

Agora você deve conseguir instalar suas dependências usando o npm. Você pode até tornar isso parte do seu processo de implantação

cd deps
npm install

Então, dentro do código do seu aplicativo, você pode obter acesso à sua versão específica do Express como este:

var express = require('myapp_dependencies').express;
Daniel Beardsley
fonte
Obrigado, este é o melhor método que vi até agora. No entanto, o require('express')in deps / index.js não importaria apenas a versão Express mais recente, e não necessariamente a que instalamos? Eu sou um novato nodeJS, por favor, tenha paciência comigo.
adamJLev
Não, essa é a mágica de npm install, ele adiciona links simbólicos dentro do diretório do seu pacote instalado para as versões corretas dos pacotes dependentes. Quando o seu pacote de dependências é necessário, o require('express')verifica o diretório local primeiro e encontra o link simbólico para a versão correta do express.
Daniel Beardsley
5

Você deve ler esses dois artigos do blog de Isaacs (autor npm). Eu acho que eles são muito bons, e acredito que dizem a você como atingir seu 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/

Acredito que o link nº 1 (ponto nº 11) explica isso:

11: Empacote todas as suas dependências no próprio pacote

Quando você usa o comando npm bundle, npm colocará todas as suas dependências na pasta node_modules em seu pacote. Mas não para por aí.

Se quiser depender de algo que não está no registro, você pode fazer isso. Basta fazer isso:

npm bundle install http://github.com/whoever/whatever/tarball/master Isso instalará o conteúdo desse tarball no pacote, e então você pode listá-lo como uma dependência, e ele não tentará instalá-lo quando seu pacote é instalado.

Isso também é útil se você tiver seu próprio fork de algo e preferir não alterar o nome.

Na verdade, você pode executar quase qualquer comando npm no pacote. Para ver o que há dentro, você pode fazer npm bundle ls. Para remover algo, faça npm bundle rm thing. E, claro, você pode instalar várias versões e ativar a que desejar.

Alfred
fonte
Isso é útil, embora não seja o que eu estava procurando. Talvez eu precise acrescentar esclarecimentos. Estou procurando uma maneira de instalar ou atualizar automaticamente (na máquina de destino) os pacotes NPM dos quais meu aplicativo depende sempre que eu o implantar. Parece que npm bundleé usado para coletar todas as suas dependências em um diretório específico diferente do padrão. Provavelmente irei encontrar minha própria solução com desempenho semelhante a bundle install( bundlerpara ruby)
Daniel Beardsley
1
Apenas uma observação, desde a npmversão 1.0+, npm bundlefoi removida. Em vez disso, apenas use o npm installcomando sem nome de pacote, ele lerá o package.json e puxará os pacotes necessários.
Arthur Maltson
2

A partir da versão 1.1.2 do Npm, há um novo comando npm shrinkwrapque cria um npm-shrinkwrapped.jsonarquivo, análogo ao Gemfile.lock. É importante fazer um, para evitar o apodrecimento do software (veja a lógica de Bundler ). Particularmente porque o Nodejs tem uma comunidade tão dinâmica.

Embora bundle installcrie um Gemfile.lockautomaticamente, npm installnão criará npm-shrinkwrapped.json(mas o usará quando existir). Portanto, você precisa se lembrar de usar npm shrinkwrap.

Leia um guia completo em http://blog.nodejs.org/2012/02/27/managing-node-js-dependencies-with-shrinkwrap/

Coronel Panic
fonte
2

Parece-me que a solução mais simples é usar um package.jsonarquivo com o privatesinalizador (adicionado ao npm no mês passado) definido como true. Dessa forma, você pode executar npm installou npm bundleobter as dependências do seu projeto, mas evita que alguém publique acidentalmente seu projeto não público.

Aqui está um exemplo package.json:

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

A execução npm installserá instalada expressno sistema local se ainda não existir; a execução npm publishdá um erro por causa do "private": true.

Você e sua equipe podem usar a tag de versão internamente para rastrear alterações de dependência ao longo do tempo - cada vez que você alterar uma dependência, altere a versão. Para ver qual versão você instalou, use npm ls installed.

Trevor Burnham
fonte
Acho que você não deve citar truee que só está funcionando porque strings são valores verdadeiros (ou seja, !!"false" === true).
Camilo Martin de
1

Publique seu aplicativo npmtambém e liste suas dependências no arquivo package.json.

Quando alguém usar npmpara instalar seu pacote, npmcuidará de resolver suas dependências.

Especificação de pacotes: http://wiki.commonjs.org/wiki/Packages/1.0

Dan Grossman
fonte
Sim, mas este é um aplicativo da web sem código aberto. Se você tem uma ideia que não envolve a publicação do aplicativo, edite sua resposta ou crie outra.
Daniel Beardsley
1
Em seguida, publique um pacote como "myapp-dependencies" que seus usuários podem usar npmpara instalar antes de instalar seu aplicativo. Não acho que haja qualquer outro gemequivalente para node.js.
Dan Grossman