Cli: [FEATURE] Não remova node_modules em npm ci

Criado em 6 dez. 2019  ·  53Comentários  ·  Fonte: npm/cli

O que? Por que

Eu realmente gostaria de ver um sinalizador como npm ci --keep para fazer uma atualização incremental em nosso buildserver, pois isso aceleraria muito nossas implantações. Como sugerido antes no github e na comunidade . A última atualização foi no dia 7 de outubro que estava sendo analisado pela equipe cli. Alguém poderia postar uma atualização sobre isso? :-)

Enhancement

Comentários muito úteis

É assim que eu gostaria que funcionasse em um mundo perfeito:

  • npm install - mesmo comportamento de hoje
  • npm install --from-lockfile - instalar a partir do arquivo de bloqueio (como ci faz)
  • npm install --clean - mesmo comportamento de npm install mas exclua o conteúdo node_modules
  • npm ci - um apelido para npm install --from-lockfile --clean

Todos 53 comentários

Não é isso que ci / cleaninstall pretende fazer. O comportamento atual está correto. O que você deseja usar é npm shrinkwrap .

Adicionamos uma atualização para evitar a exclusão de node_modules _folder_, mas não de seus _contents_ (como originalmente solicitado naquela postagem). O propósito do comando npm ci é deletar tudo para começar do zero. Se você quiser manter seus antigos node_modules, o que você precisa é de npm i .

Obrigado por suas respostas! Desculpe pela minha resposta tardia. Eu olhei para npm shrinkwrap mas ele deve ser executado em nosso servidor de compilação para integração contínua? Ao executar este comando, ele renomeia meu package-lock.json para npm-shrinkwrap.json mas o que devo então executar durante o CI? Apenas npm install para ter uma atualização incremental? Ou devo executar npm ci mas isso excluirá todos os pacotes novamente :-( O que estou procurando é um comando que faz uma atualização incremental, mas instalará exatamente o que está em nosso package-lock.json

@claudiahdz; Meu entendimento é que executar npm install durante a CI atualizará package-lock.json e isso pode significar que executar a mesma compilação algumas semanas depois instalaria pacotes diferentes. Isso está incorreto?

Ps, eu pensei que npm ci era a abreviação de Integração Contínua

Conforme referido aqui: https://github.com/npm/npm/issues/20104#issuecomment -403321557

O comportamento atual é problemático se você estiver usando npm ci dentro de um contêiner Docker (o que é bastante comum para integração contínua) e você tiver uma montagem de ligação em node_modules

Isso causa o seguinte erro:

webpack_1   | npm ERR! path /var/www/project/docker-config/webpack-dev-devmode/node_modules
webpack_1   | npm ERR! code EBUSY
webpack_1   | npm ERR! errno -16
webpack_1   | npm ERR! syscall rmdir
webpack_1   | npm ERR! EBUSY: resource busy or locked, rmdir '/var/www/project/docker-config/webpack-dev-devmode/node_modules'

o que resulta no aborto do contêiner do Docker.

Seria ótimo ter uma bandeira --no-delete ou se npm ci pudesse deletar os _contents_ de node_modules mas não o diretório em si.

ci = instalação limpa

Isso é esperado. Por que você não usa o npm i normal com um arquivo de bloqueio?

Seria ótimo ter um sinalizador --no-delete ou se o npm ci pudesse excluir o conteúdo de node_modules, mas não o próprio diretório.

rm -rf node_modules/* && npm i

ci = instalação limpa

Isso é esperado. Por que você não usa o npm i normal com um arquivo de bloqueio?

... porque: https://docs.npmjs.com/cli/ci.html

Este comando é semelhante ao npm-install, exceto que deve ser usado em ambientes automatizados, como plataformas de teste, integração contínua e implantação - ou qualquer situação em que você queira ter certeza de que está fazendo uma instalação limpa de suas dependências. Pode ser significativamente mais rápido do que uma instalação normal do npm, ignorando certos recursos orientados ao usuário. Também é mais estrito do que uma instalação normal, o que pode ajudar a detectar erros ou inconsistências causadas pelos ambientes locais instalados de forma incremental da maioria dos usuários npm.

As instalações mais rápidas e a abordagem limpa tornam isso ideal para ambientes de CI como o que mencionei acima.

rm -rf node_modules / * && npm i

Isso é o que eu faço agora, mas veja acima o desejo de usar npm ci

Parece razoável para mim apresentar um RFC pedindo um sinalizador de configuração que faça npm ci remover o conteúdo de node_modules e não o próprio dir. Isso também é um problema para mim, já que configurei o Dropbox para ignorar seletivamente um node_modules dir, mas se eu excluí-lo, essa configuração seletiva vai embora, e na próxima vez node_modules é criado, ele sincroniza.

Parece-me razoável apresentar um RFC pedindo um sinalizador de configuração que faça npm ci remover o _contents_ de node_modules e não o próprio dir. Isso também é um problema para mim, já que configurei o Dropbox para ignorar seletivamente um node_modules dir, mas se eu excluí-lo, essa configuração seletiva vai embora, e na próxima vez node_modules é criado, ele sincroniza.

Não é este também o outro problema descrito, para permitir que o npm crie arquivos para ignorar o dir (para OSX Spotlight e outros)? Acho que também houve outros que precisam desse recurso.

ci = instalação limpa

Isso é esperado. Por que você não usa o npm i normal com um arquivo de bloqueio?

npm i seria ótimo, mas somente se não mudasse o arquivo de bloqueio. Eu vi o package-lock.json ser atualizado durante um npm i ou isso não deveria acontecer?

Eu apoio esse recurso. Conforme declarado, npm i modifica package-lock.json. Uma bandeira seria a solução ideal.

mesmo, uma bandeira seria ótimo

Eu apoio esse recurso. Conforme declarado, npm i modifica package-lock.json. Uma bandeira seria a solução ideal.

Por que não adicionar um sinalizador para npm i então? Porque isso não faria muito sentido para ci = clean install no meu sentido.

Qual parte da "instalação limpa" é incompatível com a manutenção do diretório pai node_modules/ intacto (ao fazer uma instalação limpa do conteúdo real)?

Percebo que CI não significa Integração Contínua neste caso; mas uma instalação limpa geralmente é bastante útil em um ambiente de integração contínua, como a documentação deixa claro.

Este comando é semelhante ao npm-install, exceto que deve ser usado em ambientes automatizados, como plataformas de teste, integração contínua e implantação - ou qualquer situação em que você queira ter certeza de que está fazendo uma instalação limpa de suas dependências. Pode ser significativamente mais rápido do que uma instalação normal do npm, ignorando certos recursos orientados ao usuário. Também é mais estrito do que uma instalação normal, o que pode ajudar a detectar erros ou inconsistências causadas por ambientes locais instalados de forma incremental da maioria dos usuários npm.

npm ci destina-se especificamente a ser usado em ambientes automatizados, muitas vezes isso significa uma configuração baseada em Docker.

O comportamento de excluir o diretório node_module/ é problemático em uma configuração baseada em Docker, pelas razões mencionadas neste tópico.

Portanto, estamos pedindo uma opção que tornará este comando útil para a finalidade e ambiente pretendidos.

Eu apoio esse recurso. Conforme declarado, npm i modifica package-lock.json. Uma bandeira seria a solução ideal.

Por que não adicionar um sinalizador para npm i então? Porque isso não faria muito sentido para ci = clean install no meu sentido.

Eu tenho que fazer esta pergunta se existem outras diferenças entre npm install e npm ci se não, então por que ambas as opções não estão disponíveis em npm install talvez ci necessidades para se tornar um apelido como npm install --no-update-package-lock --clean-node-modules

O comportamento de excluir o diretório node_module/ é problemático em uma configuração baseada em Docker, pelas razões mencionadas neste tópico.

Na minha opinião, isso só deve acontecer uma vez na construção da imagem. Depois disso, npm i deve ser usado durante o desenvolvimento.

talvez ci precise se tornar algum apelido como npm install --no-update-package-lock --clean-node-modules

Pessoalmente, isso faz mais sentido para mim, sinalizadores adicionais para o comando npm i normal.

Sou indiferente a isso, e honestamente muito n00b com js land para ter um argumento concreto de que deve ser ci , tudo que sei é que não deve atualizar o package-lock.json e não deve remover node_modules

npm ci não atualiza o arquivo de bloqueio, ele instala a partir do arquivo de bloqueio. Isso foi introduzido para fazer uma instalação limpa, porque antes essas pessoas foram avisadas para rm -rf node_modules e executar npm i novamente. E afaik as pessoas queriam que ele não mudasse o lockfile, mas sim instalasse a partir dele.

Então npm ci nasceu. E também pula algumas coisas como a lista de pacotes instalados e a árvore e mais algumas coisas.

Veja https://blog.npmjs.org/post/171556855892/introducing-npm-ci-for-faster-more-reliable

Ele cobre um caso de uso específico.

Para outros casos de uso, devemos adicionar novos sinalizadores a npm i com os quais também podemos emular npm ci que é uma solução mais flexível e melhor do que sinalizadores para npm ci que ainda deve cobrir apenas o caso de uso atual imho. O que os usuários solicitam aqui é um pouco semelhante a yarn install --frozen-lockfile ou yarn --frozen-lockfile .

Caso contrário, os sinalizadores são espalhados por npm ci , npm i e assim por diante, o que torna um pouco mais difícil (documentação, código, ...). Pelo menos é o que eu penso. Vamos supor que npm i t tem maneiras mais poderosas e flexíveis de configurar seu comportamento.

Para outros casos de uso, devemos adicionar novos sinalizadores para npm i com o qual também podemos emular npm ci, que é uma solução mais flexível e melhor do que sinalizadores para npm ci, que ainda deve abranger apenas o caso de uso atual imho. O que os usuários solicitam aqui é um pouco semelhante a yarn install --frozen-lockfile ou yarn --frozen-lockfile.

Eu ficaria muito feliz se o recurso fosse adicionado a npm i . Devo atualizar a postagem original?

npm ci não atualiza o arquivo de bloqueio, ele instala a partir do arquivo de bloqueio. Isso foi introduzido para fazer uma instalação limpa, porque antes essas pessoas foram avisadas para rm -rf node_modules e executar npm i novamente. E afaik as pessoas queriam que ele não mudasse o lockfile, mas sim instalasse a partir dele.

Então npm ci nasceu. E também pula algumas coisas como a lista de pacotes instalados e a árvore e mais algumas coisas.

Veja https://blog.npmjs.org/post/171556855892/introducing-npm-ci-for-faster-more-reliable

Ele cobre um caso de uso específico.

Para outros casos de uso, devemos adicionar novos sinalizadores a npm i com os quais também podemos emular npm ci que é uma solução mais flexível e melhor do que sinalizadores para npm ci que ainda deve cobrir apenas o caso de uso atual imho. O que os usuários solicitam aqui é um pouco semelhante a yarn install --frozen-lockfile ou yarn --frozen-lockfile .

Como rm -rf node_modules/* não se qualifica como "limpeza"? O recurso solicitado aqui é muito semelhante ao presente no npm ci. Na minha opinião, faz mais sentido adicionar um sinalizador ao npm ci, então ele usa rm -rf node_modules/* vez de rm -rf node_modules vez de importar todo o comportamento do npm ci para o npm i.

Aliás, esse problema deve receber mais atenção e os mantenedores devem expressar suas opiniões e planos sobre isso, o uso do docker é basicamente sempre usado em CI (integração contínua), que é um dos principais casos de uso do npm ci!

Abra um RFC para esta alteração, em vez de um problema neste repo.

Para evitar confusão, eu renomearia esse problema como "vazio em vez de remover diretório node_modules em npm CI"

Minha intenção com esse problema nunca foi excluir a pasta node_modules ou apenas seu conteúdo. Foi sempre para preservar o conteúdo de node_modules mas certifique-se de que esteja atualizado e em sincronia com package-lock.json . Portanto, uma atualização incremental que segue package-lock.json .

Talvez eu esteja errado, mas sinto que há dois problemas aqui. Talvez alguém pudesse iniciar outro problema ou RFC sobre excluir apenas o conteúdo de node_modules em vez de excluir a pasta completamente? Ou eu estou esquecendo de alguma coisa?

@Zenuka todo o motivo pelo qual o npm CI é rápido e existe é porque ele ignora o diretório node_modules existente, então é muito improvável que isso mude.

Em nosso caso de uso, acho que seria mais rápido apenas verificar se a pasta nodes_modules está atualizada ou não. E se não for, atualize apenas os pacotes que devem ser atualizados (como npm i faz) Eu tenho algumas VMs dedicadas em execução como agentes de compilação, portanto, executando uma compilação e mantendo a pasta nodes_modules e todo o seu conteúdo deve ser mais rápido do que excluir tudo e reinstalá-lo. Executamos nossa construção e testes para alterações de código muito mais do que alterações em nosso package.json ou package-lock.json .

Em nosso caso de uso, acho que seria mais rápido apenas verificar se a pasta nodes_modules está atualizada ou não.

Bem, isso (o cálculo da árvore do pacote) é o que leva mais tempo. Essa verificação tornaria npm ci muito lento.

executar uma compilação e manter a pasta nodes_modules e todo o seu conteúdo deve ser mais rápido do que excluir tudo e reinstalá-lo.

Provavelmente não, é por isso que npm ci foi introduzido, o que ignora o que npm i faz (verifique a árvore do pacote).

@Zenuka npm install é a maneira mais rápida possível de fazer o que você deseja. npm ci tem apenas um propósito: fazê-lo mais rápido, excluindo node_modules para que não precise computar um diff.

Provavelmente não, é por isso que o npm ci foi introduzido, o que ignora o que o npm i faz (verifique a árvore do pacote).

Eu testei isso apenas em minha máquina (o que obviamente não é uma boa medida), mas executar npm install em uma pasta node_modules atualizada termina em 10 segundos. Executar npm ci leva alguns minutos. Você esperaria resultados diferentes?

Sou fã da sua sugestão de adicionar um sinalizador para congelar o arquivo de bloqueio com npm install .

Verificar se o que está em package-lock.json está realmente presente é muito rápido, mesmo no Windows. Consulte https://github.com/fuzzykiller/verify-node-modules.

Verificar se nada mais está presente em node_modules certamente levaria um pouco mais de tempo, mas provavelmente ainda menos de um segundo.

Com base nisso, uma versão incremental de npm ci poderia ser facilmente criada. Afinal, a árvore já foi calculada e salva em package-lock.json .

Além disso, basicamente a única razão pela qual npm ci existe é para instalar o que está em package-lock.json . Sem se intrometer em atualizações surpresa, como npm install faz.

apenas meus 2 centavos, eu pessoalmente troquei nosso infra para npm ci porque eu também estava cansado de implantar uma tag antiga npm i não iria aderir ao arquivo de bloqueio ... então, se for sério um grande problema para adicionar a bandeira no nível npm ci (que eu entendo .. é clean install está fazendo o que é dito) então npm i REALLLLLYLYY precisa desta bandeira. mas me lembro de ter pesquisado isso e também havia um tópico de problema no npm i que tinha mais de 2 anos (e ainda estava aberto), onde a equipe do npm sugeriu que as pessoas usassem npm ci lol ... isso É por isso que as pessoas desistiram do NPM no passado e apenas começaram a mexer no fio.

novamente, apenas outra perspectiva do desenvolvedor

Eu voto por adicionar a possibilidade de manter os módulos: heavy_plus_sign:.

+1 aqui - como @phyzical e @fuzzykiller disseram, não há um "ponto npm install e npm ci que MANTENHA node_modules, mas ainda respeite package-lock.json e funcione mais rápido.
Apenas execute o mais rápido possível - procure por dependências de package-lock que já existem em node_modules, e então instale tudo o que está faltando .. sem atualizações, sem deletar.

Pessoalmente, não me importa qual é ( install ou ci ) que teria isso, mas tudo isso soa como npm install deveria apenas ter sinalizadores para tudo e npm ci não precisa ser um comando separado.

Isso é um tanto frustrante, visto que npm ci foi originalmente apresentado como a solução para o mesmo problema que esta questão está levantando.

O comportamento original que várias pessoas queriam para npm install era olhar para package-lock.json vez de package.json . Queríamos um sinalizador em npm install para ativar esse comportamento. O que obtivemos em vez disso foi npm ci , porque:

o package.json descreve as dependências necessárias do seu projeto. Se o arquivo de bloqueio atual não puder satisfazê-los, o arquivo de bloqueio deve ceder. O objetivo do lockfile é criar uma instalação repetível em diferentes máquinas, não para tornar o package.json obsoleto.

Muito bem. npm install não é o lugar certo para essa opção, npm ci é. Exceto que npm ci adiciona comportamentos adicionais (limpando a pasta node_modules ) que o impedem de ser uma solução útil para o problema original. E a razão pela qual não pode haver uma bandeira em npm ci agora é porque:

ci = instalação limpa

Isso é esperado. Por que você não usa o npm i normal com um arquivo de bloqueio?

Que ... tudo bem. Eu realmente não me importo onde a bandeira é adicionada. Não tenho qualquer interesse na filosofia subjacente à interface. Mas a bandeira poderia ser adicionada em algum lugar ?

Caramba, eu não levantaria objeções, mesmo se as pessoas quisessem um terceiro comando totalmente separado, não poderia me importar menos. A única coisa que me preocupa é que, 3 anos após o início desta conversa sobre respeitar package-lock.json para instalações normais, ainda não há como obter o comportamento que estávamos originalmente pedindo.

Em meu local de trabalho, vimos bugs de pequenas atualizações de versões e correções de bugs para pacotes. Na verdade, queremos apenas procurar esses bugs durante atualizações de pacotes propositais, não queremos que nossos ambientes de desenvolvimento usem versões de pacotes diferentes dos nossos ambientes de produção. A consistência aí é muito importante. O que quer que alguém queira chamá-lo ou onde quer que alguém queira colocá-lo, nós queremos uma maneira rápida de obter pacotes do lockfile que também não exija que passemos por node-gyp builds para módulos já instalados toda vez que execute o comando.

É assim que eu gostaria que funcionasse em um mundo perfeito:

  • npm install - mesmo comportamento de hoje
  • npm install --from-lockfile - instalar a partir do arquivo de bloqueio (como ci faz)
  • npm install --clean - mesmo comportamento de npm install mas exclua o conteúdo node_modules
  • npm ci - um apelido para npm install --from-lockfile --clean

@jdussouillez Isso é exatamente o que deveria acontecer. Muito bem dito! Eu adoraria ver essa solução implementada.

É sempre frustrante encontrar esse problema em que temos que decidir entre velocidade e consistência para um pipeline de CI. Já me deparei com isso 3 ou 4 vezes por motivos diferentes, apenas nos últimos 2 meses.

Esse recurso seria ótimo para Azure Pipelines e outras arquiteturas de nuvem.

https://docs.microsoft.com/en-us/azure/devops/pipelines/release/caching?view=azure-devops#tip

Como o npm ci exclui a pasta node_modules para garantir que um conjunto consistente e repetível de módulos seja usado, você deve evitar o armazenamento em cache de node_modules ao chamar npm ci.

Encerramento: Como @claudiahdz mencionou, npm ci não remove mais a pasta node_nodules si, mas apenas seu conteúdo (ref. Https://github.com/npm /libcipm/blob/latest/CHANGELOG.md#407-2019-10-09). Isso foi enviado em [email protected] volta em 21 de julho (ref. Https://github.com/npm/cli/blob/v6/CHANGELOG.md#6147-2020-07-21) e nós mantemos a mesma experiência em npm@7 .

Se você tiver um problema separado com npm ci ou qualquer outro comando, use um de nossos modelos de problemas para registrar um bug: https://github.com/npm/cli/issues/new/choose


Notas laterais ...

@jdussouillez agradece o feedback; Em termos de instalação diretamente de um arquivo de bloqueio - você pode fazer isso hoje com a sinalização --package-lock-only (ex. npm install --package-lock-only ). Em termos de adicionar uma bandeira --clean a install , não acho que isso agregue muito valor, mas posso estar errado. Se você acredita nisso, adoraríamos que você enviasse um RFC em https://github.com/npm/rfcs

O comentário feito por @claudiahdz quase um ano atrás parece estar relacionado a garantir que o comportamento npm ci seja excluir o conteúdo node_modules , ao invés da própria pasta. O que é útil ao montá-lo em um contêiner do docker (por exemplo), mas ainda não altera o resultado final - npm ci fará o download de todas as dependências do zero.

Usar npm install --package-lock-only parece estar fazendo exatamente o oposto do problema original (se bem entendi) - ele apenas atualizará o arquivo package-lock.json e não baixará nenhuma dependência.

O que entendi do problema original é a necessidade de ter uma opção que obtenha um estado atual da pasta node_modules e um arquivo package-lock.json e baixe apenas os pacotes necessários para obter o node_modules versões para combinar com package-lock.json . Portanto, será muito mais rápido do que baixar tudo todas as vezes, com o mesmo resultado líquido no final.

Não é isso que npm install sempre faz?

Não é isso que npm install sempre faz?

ATÉ ONDE SEI -
npm install resolverá todas as dependências de acordo com o arquivo package.json (ignorando o package-lock.json ), compare com o que está atualmente na pasta node_modules e baixe o dependências que precisam ser baixadas para atender aos requisitos. Ele também atualizará o package-lock.json acordo.

Definitivamente, ele não ignora o arquivo de bloqueio - ele apenas leva em consideração a árvore existente, o que npm ci não faz.

Você está correto, eu sinto muito.
Lembrei-me incorretamente (talvez fosse esse o comportamento no passado?). Apenas fiz alguns testes com uma árvore dep simples, e quando o arquivo package-lock.json está presente, npm i instala exatamente as versões que especifica e não muda nada. Esse era exatamente o comportamento que eu procurava, então estou feliz com isso. 👍
Peço desculpas por postar em um problema encerrado.

Minha solicitação original foi de fato o que ATGardner descreve:

O que entendi do problema original é a necessidade de ter uma opção que obtenha um estado atual da pasta node_modules e um arquivo package-lock.json e baixe apenas os pacotes necessários para obter o node_modules versões para combinar com package-lock.json . Portanto, será muito mais rápido do que baixar tudo todas as vezes, com o mesmo resultado líquido no final.

Minha experiência com npm install é que às vezes ele atualiza o arquivo package-lock.json . Eu testei isso novamente esta manhã com um repositório que eu não atualizava há algum tempo e executou git pull e npm i . Na verdade, não atualizou nenhuma versão desta vez, apenas adicionou algumas dependências e pacotes extras.
image
Infelizmente, este é um repositório privado, mas talvez outra pessoa como um repositório público reproduzível? Onde há vários commits e alternar entre eles faz com que npm install atualize package-lock.json ?

Sei que pode haver algum erro do usuário envolvido ao não confirmar package-lock.json ao atualizar package.json mas meus colegas sabem que também devem atualizar package-lock.json . Vou dar uma olhada nisso.

Não consegui obter meu exemplo simples para fazer npm i alterar o arquivo package-lock.json . Mas vou tentar mais um pouco.

Se npm i sempre acaba baixando exatamente as mesmas versões especificadas em package-lock.json , enquanto mantém o máximo possível dos node_modules atuais, por que eu precisaria executar npm ci ? qual seria a vantagem de excluir tudo antes de baixar novamente?

Peço desculpas novamente por este não ser o lugar para esta discussão. Existe algum outro lugar mais preferível?

Eu ainda não entendo. Se o estado de node_modules após a execução de npm i corresponder exatamente a package-lock.json , e o estado de node_modules após a execução de npm ci terá exatamente o mesmo resultado final - em quase todos os cenários, supondo que o computador no qual você está construindo já tenha algumas / a maioria das dependências na pasta, npm i não seria mais rápido? Ele simplesmente não fará o download do que já está presente localmente e corresponde à versão necessária.

Por que eu preferiria excluir e baixar tudo do zero?

Não, npm ci ainda é mais rápido, pois não verifica o deptree novamente, algumas saídas de console não são feitas.

Por que eu preferiria excluir e baixar tudo do zero?

Para evitar problemas e ci é para ambientes específicos, como implantações.
Acho que os documentos já mencionam as diferenças.

Pode ser significativamente mais rápido do que uma instalação normal do npm, ignorando certos recursos orientados ao usuário. Também é mais estrito do que uma instalação normal, o que pode ajudar a detectar erros ou inconsistências causadas por ambientes locais instalados de forma incremental da maioria dos usuários npm.

Veja também https://blog.npmjs.org/post/171556855892/introducing-npm-ci-for-faster-more-reliable

npm ci ainda é mais rápido.

Portanto, ao usar npm i , o tempo que leva para ler o node_modules atual e descobrir quais pacotes devem ser baixados é significativamente maior do que o tempo que leva para realmente baixar todos os pacotes do npm's servidores? Adoraria ver um experimento real que o medisse.

E eu também não entendo este parágrafo -

npm ci bypasses a package’s package.json to install modules from a package’s lockfile. This ensures reproducible builds—you are getting exactly what you expect on every install.

Não acabamos de concluir aqui que a execução de npm i usa as versões exatas no arquivo package-lock.json , e o estado de node_modules após a execução é idêntico ao estado que usaria depois de executar npm ci ? Portanto, as compilações serão igualmente reproduzíveis.

ATUALIZAR:

Eu fiz o seguinte teste -
Criei um novo projeto create-react-app . Após completar sua inicialização, ele tinha um package.json com 7 dependências diretas e um package-lock.json que continha pacotes de 1982.
Neste estado ( node_modules contém todas as dependências) - executando npm i takes

real    0m2.548s
user    0m2.659s
sys     0m0.182s

Quando eu apaguei uma única pasta de pacote ( node_modules/babel-eslint ) e, em seguida, executei npm i novamente, demorou

real    0m3.295s
user    0m3.543s
sys     0m0.434s

para baixar novamente a dependência ausente

Quando eu apaguei toda a pasta node_moduels e executei npm i novamente, demorou

real    0m16.701s
user    0m19.251s
sys     0m10.379s

Quando executei npm ci , demorou

real    0m20.997s
user    0m23.844s
sys     0m14.857s

Isso não diferiu muito quando tentei remover um único pacote ou até mesmo excluir a pasta node_modules inteira manualmente antes da chamada. Não foi surpreendente, já que npm ci começa excluindo o conteúdo de node_modules qualquer maneira.

Após cada execução, executei diff -q -r node_modules_orig/ node_modules/ para ter certeza de que o resultado é idêntico às dependências originais. Sempre foi.

Então, para concluir - parece que usar npm ci leva cerca de 21 segundos na minha máquina, independentemente do estado atual de node_modules . Usar npm i em um projeto recentemente clonado (sem node_modules ) leva cerca de 18 segundos e executá-lo em um projeto que não mudou de dependências (o node_modules atual corresponde às dependências necessárias ) leva cerca de 3 segundos.

Então, quando usar npm ci seria preferível? Não parece mais rápido (embora, é claro, este seja apenas um único teste), e o resultado final é idêntico a npm i , então a compilação subsequente seria tão confiável.

npm ci é preferível quando você precisa _exatamente_ o que está em package-lock.json e nada mais. npm i não garante que irá instalar exatamente o que está em package-lock.json . Isso ocorre por design. Embora package-lock.json seja uma entrada para npm i , também é uma saída.

Acredito que existam apenas alguns casos em que npm i instalaria algo diferente (e, portanto, modificaria package-lock.json ), como talvez versões de pacote que foram excluídas temporariamente.

Na época em que npm ci foi introduzido pela primeira vez, npm i ignorou package-lock.json imediatamente ou pelo menos foi muito mais pró-ativo na instalação de versões diferentes.

De qualquer forma, isso realmente não importa. npm ci só está OK quando a pasta node_modules ainda não existe. Caso contrário, é proibitivamente lento, especialmente no Windows. Então npm i simplesmente precisa de um sinalizador que _garantese_ que não vai modificar package-lock.json e instalar exatamente o que está dentro de package-lock.json .

Não vejo sentido em discutir mais o porquê e como. Ou vamos conseguir ou não. Como está, npm ci é uma merda.

/atualizar:
Aqui está um repositório em que a execução de npm i mudará package-lock.json : https://github.com/fuzzykiller/npm-install-demo

Embora as mudanças sejam apenas de natureza técnica, ainda não são aceitáveis.

Apenas para reiterar rapidamente:

  • npm ci sempre exclui o conteúdo de node_modules por design, o que é indesejável para compilações de não produção porque é lento. No entanto, ele usa versões exatas dos pacotes encontrados em package-lock.json , o que é desejável para várias situações.

  • npm install apenas atualiza o conteúdo de node_modules , que tem um ótimo desempenho, mas por design ignora o conteúdo de package-lock.json se package.json números da versão forem diferentes, o que é indesejável para várias situações.

  • npm install --package-lock-only é descrito nos documentos :

    O argumento --package-lock-only atualizará apenas o package-lock.json, em vez de verificar node_modules e baixar dependências.

    Isso não parece útil para nenhum dos cenários descritos acima.

O que as pessoas têm pedido nos últimos 3 anos:

  1. Um comando (em qualquer lugar) que irá ignorar package.json e _somente_ respeitar package-lock.json como a fonte definitiva de quais pacotes serão instalados.

  2. Isso não excluirá todo o conteúdo de node_modules e fará o download novamente do zero.

Pelo que posso ver tanto da documentação quanto dos testes locais, npm install satisfaz o ponto 2, mas não 1. npm ci satisfaz o ponto 1, mas não 2. npm install --package-lock-only não satisfaz nenhum desses requisitos.

Não tenho certeza do motivo pelo qual esse problema foi resolvido, ainda não há como obter o comportamento desejado.


Edit: para estender o exemplo de @fuzzykiller , não é apenas que package-lock.json é atualizado. Isso seria irritante, mas não quebraria nenhuma das minhas construções. Mas se package.json tiver dependências difusas listadas em qualquer lugar e uma versão de correção de bug dessas dependências for lançada, elas serão alteradas quando eu executar npm install em uma nova máquina. De repente, instalei diferenças entre duas máquinas. Encontramos bugs em minha empresa exatamente por causa desse comportamento, não é apenas que package-lock.json precisa ser verificado no Git novamente.

É desejável nessa situação ter um comando que se comporte como npm ci - que faça uma instalação reproduzível com base _apenas_ no conteúdo de package-lock.json . No entanto, excluir o conteúdo da pasta node_modules retarda as compilações demais para alguns ambientes e situações, embora seja um comportamento apropriado para uma compilação de produção final.

Pode haver um sinalizador em qualquer lugar para resolver esse problema. Pode ser npm install --from-lockfile . Pode ser npm ci --preserve-existing . Mas agora parece que estamos em um círculo onde qualquer um que pede um sinalizador para ser adicionado a npm install é apontado para npm ci como a solução, e qualquer um que pede um sinalizador em npm ci é apontado para npm install como a solução. Este problema foi encerrado apontando para npm install --package-lock-only , mas essa bandeira é quase o oposto do que as pessoas estão pedindo. Ele não respeita package-lock.json como fonte oficial e também não atualiza ou instala nenhuma das dependências na pasta node_modules :)

Este problema deve ser reaberto.

Esta página foi útil?
0 / 5 - 0 avaliações