Para de usar `npm install` pra instalar dependências.
Tenho duas perguntas pra ti:
- Tu inclui o
package-lock.json
no teu controle de versão? - Tu usa
npm install
pra instalar dependências de um projeto quando só quer rodar ele?
Vou procurar responder aqui o que acho que é correto, sempre considerando a possibilidade de estar errado e aberto à crítica de vocês.
Sim, tu deveria colocar o package-lock.json
no controle de versão, e atualizar ele sempre que é alterado. Não, tu não deveria usar npm install
pra meramente instalar as dependências de um repositório que clonou ou deu pull.
A ideia toda do package-lock.json
é manter as dependências da tua aplicação reprodutíveis. Clonou um repositório e só quer rodá-lo? O package-lock.json
garante que, em qualquer lugar que ele seja clonado, as dependências que vão ser baixadas sejam iguais.
Mas, pra fins de manter essa reprodutibilidade, tu não pode chegar lá e alterar o arquivo bem na hora que vai baixar as dependências. O package.json
sabe quais as dependências imediatas que tu especificou, mas só o package-lock.json
sabe que subdependências estas dependências estão usando.
Pois bem: são exatamente alterações inadvertidas que o npm install
acaba fazendo. Ele potencialmente atualiza as dependências de dependências dentro do package-lock.json
, o que é uma boa, mas deveria ser feito conscientemente e não por acidente -- e, se feito, deveria ser atualizado no controle de versão também. A questão é que, se tu muda teu package-lock.json
toda vez que instala dependências... bem, acho que é o mesmo que não ter o arquivo.
Deste modo, pra só instalar as dependências de um repositório antes de rodá-lo, o correto (até onde eu tenha sido capaz de confirmar) seria usar o comando npm ci
. Algumas pessoas veem este comando usado em Dockerfile
s e similares, e parecem acreditar que o comando tenha diretamente a ver com "continuous integration". Mas, na verdade, o ci
neste caso significa clean install
. O que ele faz? Ele baixa as dependências sem alterar o package.json
ou o package-lock.json
. Se ambos os arquivos estão fora de sincronia, caso que pode ocorrer quando alterações ao package-lock.json
não são atualizadas no controle de versão, o npm ci
falha, e daí, sim, pode-se usar o npm install
para arrumar a coisa toda. Mas ocorrências como estas deveriam ser raras, e rodar o npm install
deveria ser usado somente para instalar novas dependências (e talvez pra instalar atualizações destas e suas próprias subdependências? Sinceramente não tenho certeza).
Takeaways
- Usa o
npm install
pra adicionar dependências - Usa o
npm ci
para recriar o ambiente de dependências de um repositório pra rodar ele - Outra coisa: usa o
npm uninstall
pra remover uma dependência, isto deve alterar opackage-lock.json
; não é só ir lá e manualmente apagar a linha que lista a dependência
Novamente, fico aberto a observações com possíveis melhorias, ou que demonstrem que estou equivocadamente propondo algo que não é melhor prática. Agradeço pela atenção de vocês.
Discordo. Se as dependencias no package.json estiver bem escrito, o npm install não irá fazer alterações (significativas).
Costumo deixar minhas dependências apenas com tolerância aos patches, assim não há quebra de funcionalidade.
Porém há sim o risco de algum pacote na cadeia inserir uma breaking change em um patch, o que não é correto mas é possível.
Só acrescentaria que o npm ci
deve ser utilizado primariamente em processos de automações que incluem: plataformas de testes, integrações contínuas e implantação em ambiente produtivo. Você utiliza nesses ambientes porque você quer evitar problemas na automação. Em ambiente de desenvolvimento ainda é recomendado utilizar o npm install
.
No npm ci
você quer replicar exatamente um ambiente que já está validado com todas as suas dependências e subdependências. Você não quer correr o risco de atualizar alguma dependência na árvore do ESLint e não conseguir gerar a build. Também é por isso que você só deve utilizar o comando npm ci
em ambientes automáticos ou de implantação, você precisa sempre validar as vulnerabilidades e bugs do seu código em ambiente de desenvolvimento.
Concordo, em um dos projetos que trabalho com certa frequência sempre utilizo o npm ci
, isso pq o projeto é legado (7 anos), e utilizamos o node 14 nele, ao rodar npm install
acaba modificando o package-lock.json e a chance de algo dar errado é enorme. Então para projetos legados pelo menos, acredito que seja a melhor opção.
Que massa esse tab! Eu não conhecia o comando npm ci
, pensei como muitos que seria algo relacionado ao Continuous Integrator.
Sim, sobre package-lock.json
, eu sempre coloco ele no controle de versão. E recentemente tenho usado o pnpm
, que tem um arquivo de manifesto das dependências das dependências diferente do npm
, e a experiência tem sido muito legal!!
E outra coisa, eu acho que nesse trecho do seu tab:
"O package-lock.json sabe quais as dependências imediatas que tu especificou, mas só o package-lock.json sabe que dependências estas dependências estão usando."
Seria primeiro o package.json
e depois o package-lock.json
, certo? Se não for, desconsidera.
Ele arrumou! ^^
Sensacional mano. É aquela coisa, sempre aprendendo algo novo. Obrigado.
É até interessante seu ponto de vista.
Mas pra ser sincero, nunca tive problemas utilizando apenas o npm install
.
Vou pesquisar mais a fundo sobre o comando npm ci
pra entender melhor o funcionamento.
Obrigado por trazer esse tema em discussão.
Interessante. Geralmente eu uso yarn, mais por costume mesmo, nem sei se faz alguma diferença de fato. Teria algo equivalente pro yarn também?
Me parece algo interessante para projetos legados, como um colega que comentou aqui falou. Mas no geral, para projetos com versões mais atuais, acho que seria meio redundante as duas perguntas, não? O npm install
acaba chegando no mesmo fim do npm ci
e o package-lock.json
poderia ser setado com opcional quando se fala de controle de versão. Não sei se estou correto no meu pensamento, aberto a comentários. :)
Entendo e reconheço a validade do seu ponto de vista, concordando em grande medida com ele. No entanto, é crucial estarmos cientes dos potenciais ataques que o "package lock" pode sofrer ao adotar essa estratégia. Recomendo que use a ferramenta "npm audit".
O "npm audit" é uma ferramenta que analisa as dependências do projeto em busca de vulnerabilidades conhecidas e fornece detalhes, juntamente com recomendações de correção, para garantir maior segurança.
Além disso, uma alternativa ao uso do "package lock" é especificar versões estáticas das dependências no "package.json", o que nos permite ter maior controle sobre as versões exatas dos pacotes que estamos utilizando, minimizando riscos associados a atualizações inesperadas ou incompatibilidades.
Boa. Noa ultimos meses comecei a usar o pnpm. Ele é muito rápido e tem umas saidas legais no terminal quando você atualiza ou instala alguma coisa. Gostei bastante.
Ja me ocorreu de uma falha em comunicação a um banco Firebird com nodejs e a biblioteca node-firebird devido a uma dependência incorreta. Bem surpreendente considerando que a diferença das versões era bem pequena.
Bom post no meu ponto de vista, não sabia deste comando. Obrigado