Devo fazer o check-in do node_modules para git ao criar um aplicativo node.js no Heroku?

368

Segui as instruções básicas de introdução ao node.js no Heroku aqui:

https://devcenter.heroku.com/categories/nodejs

Essas instruções não dizem para você criar um node_modules .gitignore e, portanto, implica que o node_modules deve ser registrado no git. Quando incluo node_modules no git, meu aplicativo de iniciação é executado corretamente.

Quando segui o exemplo mais avançado em:

https://devcenter.heroku.com/articles/realtime-polyglot-app-node-ruby-mongodb-socketio https://github.com/mongolab/tractorpush-server (fonte)

Ele me instruiu a adicionar node_modules ao .gitignore. Portanto, removi o node_modules do git, o adicionei ao .gitignore e reimplantei. Desta vez, o implementado falhou da seguinte forma:

-----> Heroku receiving push
-----> Node.js app detected
-----> Resolving engine versions
       Using Node.js version: 0.8.2
       Using npm version: 1.0.106
-----> Fetching Node.js binaries
-----> Vendoring node into slug
-----> Installing dependencies with npm
       Error: npm doesn't work with node v0.8.2
       Required: node@0.4 || 0.5 || 0.6
           at /tmp/node-npm-5iGk/bin/npm-cli.js:57:23
           at Object.<anonymous> (/tmp/node-npm-5iGk/bin/npm-cli.js:77:3)
           at Module._compile (module.js:449:26)
           at Object.Module._extensions..js (module.js:467:10)
           at Module.load (module.js:356:32)
           at Function.Module._load (module.js:312:12)
           at Module.require (module.js:362:17)
           at require (module.js:378:17)
           at Object.<anonymous> (/tmp/node-npm-5iGk/cli.js:2:1)
           at Module._compile (module.js:449:26)
       Error: npm doesn't work with node v0.8.2
       Required: node@0.4 || 0.5 || 0.6
           at /tmp/node-npm-5iGk/bin/npm-cli.js:57:23
           at Object.<anonymous> (/tmp/node-npm-5iGk/bin/npm-cli.js:77:3)
           at Module._compile (module.js:449:26)
           at Object.Module._extensions..js (module.js:467:10)
           at Module.load (module.js:356:32)
           at Function.Module._load (module.js:312:12)
           at Module.require (module.js:362:17)
           at require (module.js:378:17)
           at Object.<anonymous> (/tmp/node-npm-5iGk/cli.js:2:1)
           at Module._compile (module.js:449:26)
       Dependencies installed
-----> Discovering process types
       Procfile declares types -> mongod, redis, web
-----> Compiled slug size is 5.0MB
-----> Launching... done, v9

A execução de "heroku ps" confirma a falha. Ok, não há problema, então revirei a alteração, adicione node_module novamente ao repositório git e removi-o do .gitignore. No entanto, mesmo após a reversão, ainda recebo a mesma mensagem de erro na implantação, mas agora o aplicativo está sendo executado corretamente novamente. A execução de "heroku ps" indica que o aplicativo está sendo executado.

Então, minha pergunta é qual é o caminho certo para fazer isso? Incluir node_modules ou não? E por que eu continuaria recebendo a mensagem de erro quando reverter? Meu palpite é que o repositório git está em um estado ruim no lado Heroku?

Jason Griffin
fonte
10
Eu sou o proprietário do idioma Node no Heroku e a resposta é simples: Não. Não faça check- node_modulesin nos aplicativos Heroku.
Hunterloftis
@hunterloftis 'Não marque node_modules em ' ou 'Não marque node_modules em '? Para esclarecer, como proprietário da linguagem Node no Heroku, você deseja que carregemos todo o node_modules por meio do nosso git push ou não? Prefiro não devido ao desperdício de largura de banda e ao fato de o Heroku os colocar no backend do meu git push; no entanto, tive que editar arquivos nos meus node_modules manualmente para fazer com que o Heroku carregasse meu aplicativo. Portanto, tive que ignorar node_modules menos todo o módulo que incluía meu arquivo editado para que ele funcionasse.
ZStoneDPM 9/01

Respostas:

400

Segunda atualização

O FAQ não está mais disponível.

A partir da documentação de shrinkwrap:

Se você deseja bloquear os bytes específicos incluídos em um pacote, por exemplo, para ter 100% de confiança em poder reproduzir uma implantação ou compilação, deve verificar suas dependências no controle de origem ou seguir algum outro mecanismo que possa verificar conteúdo em vez de versões.

Shannon e Steven mencionaram isso antes, mas acho que deve fazer parte da resposta aceita.


Atualizar

A fonte listada para a recomendação abaixo foi atualizada . Eles não recomendam mais que a node_modulespasta seja confirmada.

Geralmente não. Permita que o npm resolva dependências para seus pacotes.

Para pacotes implantados, como sites e aplicativos, você deve usar o npm shrinkwrap para bloquear sua árvore de dependência completa:

https://docs.npmjs.com/cli/shrinkwrap


Correio Original

Para referência, as perguntas frequentes do npm respondem à sua pergunta claramente:

Verifique node_modules no git para itens que você implanta, como sites e aplicativos. Não verifique node_modules no git para bibliotecas e módulos destinados a serem reutilizados. Use o npm para gerenciar dependências no seu ambiente de desenvolvimento, mas não nos scripts de implantação.

e, para uma boa justificativa, leia o post de Mikeal Rogers sobre isso .


Fonte: https://docs.npmjs.com/misc/faq#should-i-check-my-node-modules-folder-into-git

Kostia
fonte
13
Isso não está correto - na verdade, é uma péssima idéia. Se você estiver desenvolvendo no Windows e implementando no Linux, precisará reconstruir o node_modules ao implantar. O que significa - caos. Muitos arquivos modificados e nenhuma idéia do que fazer.
user3690202
8
Isso não é possível - alguns de nossos desenvolvedores desenvolvem janelas de direcionamento, outros visando o linux, mas a mesma base de código. A melhor abordagem seria não confirmar os módulos do nó - oops.
user3690202
7
@ user3690202 Parece que você tem um caso muito convencional, e não a norma, então dizer "isso não está correto" é provavelmente um exagero. Dito isto, não tenho certeza qual é o seu caso de uso exato, mas não consigo pensar em nenhuma razão para usar o Windows e o Linux para desenvolvimento. Atenha-se a um e execute testes ou controle de qualidade em todas as plataformas, com seu suporte.
Kostia
16
@Kostia Nosso caso de uso é bastante comum. Somos voluntários e usamos nossas próprias máquinas, não as da empresa. Parece uma situação bastante comum para código aberto.
Adam
4
@ Adam tangencialmente, você poderia adicionar os arquivos que estão sendo compilados .gitignore? Dessa forma, a fonte está no git e quaisquer componentes compilados não são, da mesma forma que as pastas distou outputsão atribuídas nos projetos grunt e gulp.
214 Kostia #
160

Minha maior preocupação em não fazer o check node_modules-in do git é que 10 anos depois, quando seu aplicativo de produção ainda estiver em uso, o npm pode não estar por aí. Ou o npm pode ficar corrompido; ou os mantenedores podem decidir remover a biblioteca na qual você confia do repositório; ou a versão que você usa pode ser cortada.

Isso pode ser mitigado com gerentes de repositório como o maven, porque você sempre pode usar o seu Nexus ou Artifactory local para manter um espelho com os pacotes que você usa. Tanto quanto eu entendo, esse sistema não existe para npm. O mesmo vale para gerentes de bibliotecas do lado do cliente, como Bower e Jamjs.

Se você comprometeu os arquivos em seu próprio repositório git, pode atualizá-los quando quiser e tem o conforto de construções repetíveis e o conhecimento de que seu aplicativo não será interrompido devido a alguma ação de terceiros.

Jonathan
fonte
10
Hoje existem muitas opções: Nexus ( Issues.sonatype.org/browse/NEXUS-5852 ), Artifactory ( jfrog.com/jira/browse/RTFACT-5143 ), npm_lazy ( github.com/mixu/npm_lazy ), npm-lazy- espelho ( npmjs.org/package/npm-lazy-mirror ), etc.
Johann
4
Citação das perguntas frequentes do npmjs: "Se você é paranóico, dependendo do ecossistema npm, deve executar um espelho npm privado ou um cache privado.". Eu acho que isso aponta para o problema que você está se referindo, certo?
Taylan
3
Um caso em questão developers.slashdot.org/story/16/03/23/0652204/…
prototype
2
O Npm não desaparecerá durante a noite, portanto, o benefício não se combina muito bem com a perda de clareza no seu histórico de consolidação e seu enorme tamanho de pacote. Se alguém estiver criando um aplicativo que eles acham que ainda estará ativo em 10 anos, é razoável esperar que ele receba muita manutenção ao longo do caminho. O argumento sobre interrupções no NPM é um argumento muito melhor, embora haja provavelmente melhores maneiras de mitigar esse risco do que se comprometer com a fonte.
Sam P
3
Mesmo um mês no caminho é perigoso se você não confirmar suas dependências (de preferência em um repositório separado). Como descobri uma manhã, quando clonei um dos meus projetos e descobri que uma versão do pacote havia sido removida do npm. Passei meio dia alterando todas as minhas versões de dependências em cascata para que a atualização do npm funcionasse e construísse novamente.
Richard
67

Você deve não incluem node_modules em sua .gitignore(ou melhor, você deve incluir node_modules na sua fonte implantado para Heroku).

Se node_modules:

  • existe então npm installusará essas bibliotecas vendidas e reconstruirá quaisquer dependências binárias com npm rebuild.
  • não existe , npm installserá necessário buscar todas as dependências, o que adiciona tempo à etapa de compilação do slug.

Consulte a fonte do buildpack do Node.js. para obter essas etapas exatas

No entanto, o erro original parece ser uma incompatibilidade entre as versões de npme node. É uma boa idéia sempre definir explicitamente a enginesseção de packages.jsonacordo com este guia para evitar esses tipos de situações:

{
  "name": "myapp",
  "version": "0.0.1",
  "engines": {
    "node": "0.8.x",
    "npm":  "1.1.x"
  }
}

Isso garantirá a paridade de desenvolvimento / produto e reduzirá a probabilidade de tais situações no futuro.

Ryan Daigle
fonte
Obrigado pela ajuda Ryan. Isso me levou ao erro da versão do npm, mas agora falha ao compilar o pacote redis. A mensagem de erro é "OSError: [Erro 2] Nenhum arquivo ou diretório: '/ Usuários / Jason / tastemade / tastebase / node_modules / redis-url / node_modules / redis / node_modules / hiredis / build'". Parece que ele está usando um caminho da minha caixa local nos servidores heroku. Existem certos arquivos nos node_modules que preciso adicionar ao .gitignore?
Jason Griffin
Não tenho certeza do que está acontecendo com essa biblioteca específica, mas eu tentaria excluir node_modules do git nesse caso e ver se isso ajuda (forçando o npm a buscar tudo sozinho e garantindo um ambiente de construção novo).
precisa
A melhor prática do @RyanDaigle agora (novembro de 2013) recomendada pelo npm ( npmjs.org/doc/… ) e pelo heroku ( devcenter.heroku.com/articles/… ) é fazer o check-in do node_modules para o git. Você atualizaria sua resposta (pois possui o faturamento superior)?
precisa
Ao pressionar heroku, você obtém a saída "-----> Caching node_modules directory para futuras compilações". Isso é para diminuir a compilação futura de lesmas.
Ph3nx
Eu tenho um problema que o caminho do arquivo node_modules é muito longo para confirmar. O Git não encontrará os arquivos.
Code Pharaoh
22

Eu deixaria isso após este comentário: Devo fazer o check-in do node_modules para git ao criar um aplicativo node.js no Heroku?

Mas o stackoverflow estava formatando isso de forma estranha. Se você não tiver máquinas idênticas e estiver efetuando check-in em node_modules, faça um .gitignore nas extensões nativas. Nosso .gitignore se parece com:

# Ignore native extensions in the node_modules folder (things changed by npm rebuild)
node_modules/**/*.node
node_modules/**/*.o
node_modules/**/*.a
node_modules/**/*.mk
node_modules/**/*.gypi
node_modules/**/*.target
node_modules/**/.deps/
node_modules/**/build/Makefile
node_modules/**/**/build/Makefile

Teste isso primeiro verificando tudo e peça a outro desenvolvedor que faça o seguinte:

rm -rf node_modules
git checkout -- node_modules
npm rebuild
git status

Verifique se nenhum arquivo foi alterado.

ibash
fonte
Acabei de adicionar isso. Resolvido meu problema. O github do Windows continuava travando, tentando passar por mais de 7000 arquivos node_module: /
Batman
10

Eu acredito que isso npm installnão deve ser executado em um ambiente de produção. Há várias coisas que podem dar errado - interrupção da NPM, o download de dependências mais recentes (o shrinkwrap parece ter resolvido isso) são duas delas.

Por outro lado, node_modulesnão deve ser cometido no git. Além de seu grande tamanho, confirmações incluindo eles podem se tornar uma distração.

As melhores soluções seriam: npm installdevem ser executadas em um ambiente de IC que seja semelhante ao ambiente de produção. Todos os testes serão executados e um arquivo compactado será criado, incluindo todas as dependências.

user2468170
fonte
Por que você teria uma etapa executada no IC que não executaria como parte de sua implantação? Isso significa que você não tem paridade entre os 2 sistemas! Como a resposta diz acima - comprometer a pasta simplesmente ignorar as extensões nativas, de que maneira você está coberto de coisas como falhas de NPM
Voycey
11
Obrigado por seu comentário. Acredito que os node_modules que são executados no seu servidor de produção devem ser gerados a partir de uma instalação npm, não do que os desenvolvedores tenham confirmado. A pasta node_modules de um desenvolvedor não corresponde necessariamente ao conteúdo do package.json.
user2468170
8

Eu tenho usado tanto a pasta node_modules como a embalagem. Ambas as soluções não me fizeram feliz.

Em resumo: o node_modules comprometido adiciona muito ruído ao repositório.
E o shrinkwrap.json não é fácil de gerenciar e não há garantia de que algum projeto envolto em contração será construído em alguns anos.

Eu descobri que a Mozilla estava usando um repositório separado para um de seus projetos https://github.com/mozilla-b2g/gaia-node-modules

Portanto, não demorou muito para implementar essa ideia em uma ferramenta CLI do nó https://github.com/bestander/npm-git-lock

Antes de cada compilação, adicione
npm-git-lock --repo [[email protected]: seu / dedicado / node_modules / git / repository.git]

Ele calculará o hash do seu package.json e verificará o conteúdo de node_modules de um repositório remoto, ou, se for a primeira compilação para este package.json, fará uma limpeza npm installe enviará os resultados para o repositório remoto.

bestander
fonte
5

O que funcionou para mim foi adicionar explicitamente uma versão do npm ao package.json ("npm": "1.1.x") e NÃO verificar o node_modules do git. Pode ser mais lento para implantar (já que ele baixa os pacotes a cada vez), mas não consegui compilar os pacotes quando eles fizeram o check-in. O Heroku procurava arquivos que só existiam na minha caixa local.

Jason Griffin
fonte
Se você acha que minha resposta foi correta, aceite-a? Obrigado!
Ryan Daigle
Caso isso ainda esteja em debate, eu daria uma olhada nesta postagem de stackoverflow, que é quase uma duplicata da sua pergunta acima: stackoverflow.com/questions/11459733/… Basicamente, parece que a convenção é verificar node_modules e gerencie suas versões desses módulos localmente. Isso parece bastante razoável, e talvez a explicação mais sucinta seja a seguinte: mikealrogers.com/posts/nodemodules-in-git.html Boa sorte!
warriorpostman
3

Em vez de fazer check-in node_modules, crie um arquivo package.json para o seu aplicativo.

O arquivo package.json especifica as dependências do seu aplicativo. Heroku pode então dizer ao npm para instalar todas essas dependências. O tutorial ao qual você vinculou contém uma seção nos arquivos package.json.

matzahboy
fonte
Eu tenho um package.json. Ele tem o seguinte: {"name": "node-example", "version": "0.0.1", "dependencies": {"express": "2.5.x", "redis-url": "0.1. 0 "," mongodb ":"> = 0.9.9 "}," engines ": {" node ":" 0.8.x "}}
Jason Griffin
Eu fiz na minha caixa local para criar o diretório node_modules. Foi o que fiz o check-in, depois o removi e o adicionei novamente.
Jason Griffin
Depois de examinar mais o tutorial, parece que eles estão enviando node_modules. Nesse caso, não tenho certeza se há uma maneira de não confirmar node_modules. Desculpe
matzahboy
3

Estou usando esta solução:

  1. Crie um repositório separado que retém node_modules. Se você possui módulos nativos que devem ser construídos para uma plataforma específica, crie um repositório separado para cada plataforma.
  2. Anexe esses repositórios ao seu repositório de projeto com git submodule:

git submodule add .../your_project_node_modules_windows.git node_modules_windows

git submodule add .../your_project_node_modules_linux_x86_64 node_modules_linux_x86_64

  1. Crie um link específico da plataforma node_modulespara o node_modulesdiretório e adicione-o node_modulesa .gitignore.
  2. Corra npm install.
  3. Confirme as alterações no repositório do submódulo.
  4. Confirme as alterações no repositório do projeto.

Assim, você pode alternar facilmente entre node_modulesplataformas diferentes (por exemplo, se estiver desenvolvendo no OS X e implantando no Linux).

mixel
fonte
3

De https://web.archive.org/web/20150212165006/http://www.futurealoof.com/posts/nodemodules-in-git.html :

Edit: O link original era este, mas agora está morto. Obrigado @Flavio por apontar.

Para recapitular.

  • Somente faça check-in do node_modules para aplicativos implementados, e não pacotes reutilizáveis ​​que você mantém.
  • Quaisquer dependências compiladas devem ter sua origem registrada, não os destinos de compilação e $ npm devem ser reconstruídos na implantação.

Minha parte favorita:

Todas as pessoas que adicionaram node_modules ao seu gitignore, removem essa merda, hoje é um artefato de uma época que ficamos felizes em deixar para trás. A era dos módulos globais está morta.

Benjamin Crouzier
fonte
O site que você vinculou parece ter expirado e agora está cheio de anúncios fraudulentos. Eu gostaria que esses anúncios fossem "artefatos de uma época que todos ficaríamos felizes em deixar para trás".
Flavio Copes
11
@FlavioCopes Atualizei minha resposta com o link da Wayback Machine.
Benjamin Crouzier
2

http://nodejs.org/api/modules.html

[...] o nó inicia no diretório pai do módulo atual, adiciona /node_modulese tenta carregar o módulo a partir desse local.

Se não for encontrado lá, ele será movido para o diretório pai e assim por diante , até que a raiz da árvore seja alcançada.

Se você estiver lançando seus próprios módulos específicos para seu aplicativo, poderá mantê-los ( e somente aqueles ) nos aplicativos /node_modules. E mova todas as outras dependências para o diretório pai.

Esse caso de uso é bastante impressionante, permite que você mantenha os módulos criados especificamente para o seu aplicativo de maneira agradável com ele e não confunda seu aplicativo com dependências que podem ser instaladas posteriormente.

atraso
fonte
1

Cenário 1:

Um cenário: você usa um pacote que é removido do npm. Se você tiver todos os módulos na pasta node_modules, isso não será um problema para você. Se você tiver apenas o nome do pacote no package.json, não poderá mais obtê-lo. Se um pacote tiver menos de 24 horas, você poderá removê-lo facilmente do npm. Se tiver mais de 24 horas, entre em contato com eles. Mas:

Se você entrar em contato com o suporte, eles verificarão se a remoção dessa versão do seu pacote interromperia outras instalações. Nesse caso, não o removeremos.

consulte Mais informação

Portanto, as chances são baixas, mas há o cenário 2 ...


cenário 2:

Um outro cenário em que este é o caso: você desenvolve uma versão corporativa do seu software ou um software muito importante e escreve no seu package.json:

"dependencies": {
    "studpid-package": "~1.0.1"
}

Você usa o método function1(x)desse pacote.

Agora os desenvolvedores do studpid-package renomeiam o método function1(x)para function2(x)e cometem uma falha ... Eles alteram a versão do pacote de 1.0.1para 1.1.0. Isso é um problema, porque quando você ligar npm installda próxima vez, aceitará a versão 1.1.0porque usou o til ( "studpid-package": "~1.0.1").

A chamada function1(x)pode causar erros e problemas agora.


Enviar a pasta node_modules inteira (geralmente mais de 100 MB) para o seu repositório irá custar espaço de memória. Alguns kb (apenas package.json) em comparação com centenas de MB (package.json & node_modules) ... Pense nisso.

Você poderia fazer / deveria pensar se:

  • o software é muito importante.

  • custa dinheiro quando algo falha.

  • você não confia no registro npm. o npm é centralizado e pode teoricamente ser desligado.

Você não precisa publicar a pasta node_modules em 99,9% dos casos se:

  • você desenvolve um software só para você.

  • você programou algo e só deseja publicar o resultado no GitHub porque outra pessoa pode estar interessada nele.


Se você não deseja que o node_modules esteja em seu repositório, basta criar um .gitignorearquivo e adicionar a linha node_modules.

ndsvw
fonte