Esse texto é uma tradução livre do artigoEverything You Wanted To Know About package-lock.json But Were Too Afraid To Ask.
Introdução
Então você atualizou o Node Package Manager (npm) para a versão 5.x.x e tudo parece que está funcionando bem, certo? Mas pera, o que é isso? Um novo arquivo foi criado automaticamente:package-lock.json
. Se você abri-lo até vai parecer umpackage.json
, mas com muito mais coisa, mais verboso. Você decide ignorá-lo enquanto desenvolve seu projeto. Eventualmente você se depara com um problema de dependência. Não pode ser encontrada ou uma versão errada foi instalada. A maior parte das pessoas deleta opackage-lock.json
e reexecuta onpm install
. Então por que o temos? O que deveríamos fazer? O que ele faz?
Resumo
- Se você está usando uma versão do NPM superior a 5.x.x o
package-lock.json
será gerado para você; - Você deve usar o
package-lock.json
para garantir uma instalação consistente e dependências compatíveis; - VocêDEVEcommitar seu
package-lock.json
em seu sistema de controle de versão; - A partir da versão 5.1.0 do npm o conteúdo do
package.json
é capaz de sobrescrever o que estiver nopackage-lock.json
para instalar ou modificar uma dependência, o que*deve*gerar menos dor de cabeça; - Não precisa mais deletar o
package-lock.json
e executar onpm install
para regerá-lo; - Use semver (versionamento semântico) se sua aplicação for uma API e siga as regras do semver.
Background
Versionamento Semântico (semver)
Antes de entender opackage-lock.json
e opackage.json
você precisa entender oversionamento semântico (semver). É a sacada por trás do NPM, e o que o tornou um sucesso. Você pode ler mais sobre como o NPM faz seu uso poraqui.
De forma resumida, se você está criando uma aplicação com a qual outras irão integrar, você deve comunicar como as alterações feitas afetarão a capacidade de integração desses terceiros com sua aplicação. Isso é feito através do versionamento semântico.
Uma versão é dividida em 3 partes: X, Y e Z, onde a primeira é considerada amajor(principal), a segunda, aminor(menor) e a terceira é opatch*(correção).*Um exemplo como 1.2.3 representaria que 1 é a major, a 2 é a minor, e o 3 o patch.
- Uma modificação no patch não quebrará nada. Muito pelo contrário, corrigirá algo.
- Uma alteração na versão minor lhe trará uma nova funcionalidade, mas sem quebrar o que existe atualmente.
- E por fim, alterar algo na versão major significa que houve uma quebra de compatibilidade. Se o usuário não fizer a alteração necessária, ele não conseguirá mais integrar com sua aplicação.
Gerenciando pacotes
O NPM existe para facilitar o gerenciamento de dependências. Seu projeto pode ter centenas de dependências, cada uma com suas próprias dependências. Para nos mantermos longe desse inferno de dependências, o NPM foi criado com um conjunto de comandos que permitem você instalar e gerenciar tudo isso e, dificilmente, precisar se preocupar com elas.
Quando você instala um pacote com o NPM (e o salva), uma nova entrada é adicionada ao arquivopackage.json
contendo o nome do pacote e a versão (semver) que será usada. Entretanto, existem algumas artimanhas para definir melhor as versões.
Por padrão o NPM instalará a versão mais nova do pacote, inserindo um símbolo na frente da versão^2.12.0
. Isso significa que o pacote será instalada com uma versão que seja igual ou superior a 2.12.0. Leia mais sobre semver e wildcards e brinque com umaferramenta para calcular a versão do pacote.
Projetos Compartilhados
O real benefício de ter dependências definidas nopackage.json
é que qualquer um pode ter acesso a esse arquivo e criar um pasta de dependências contendo todos os módulos para rodar sua aplicação. Mas vamos dar uma olhada em uma caso específico em que as coisas podem dar errado.
Vamos dizer que criamos um projeto utilizando oexpress. Depois de rodarnpm init
instalamos o express:npm install express --save
. Até o momento em que escrevo esse artigo, a última versão do express é a 4.15.4. Então será adicionado como dependência aopackage.json
a linhaexpress: ^4.15.4
, e isso informará exatamente a versão que será instalada em meu computador.
Não agora, mas talvez amanhã, o pessoal que desenvolve o express pode lançar um bug fix, então a nova versão será a 4.15.5. Então se alguém quiser contribuir com meu projeto, precisará cloná-lo e rodar o comandonpm install
. Com isso ele terá instalado em seu computador a versão 4.15.5. Nós dois teremos o express instalado, mas versões diferentes. Teoricamente ambas devem ser compatíveis, mas talvez esse bug fix afete alguma funcionalidade que fazemos uso, e nossa aplicação poderá produzir resultados diferentes, já que uma possui a versão 4.15.4, e outra a 4.15.5.
Package-lock
O objetivo
A proposta dopackage-lock
é evitar que situações como o caso acima, onde módulos instalados a partir do mesmopackage.json
resulte em duas diferentes instalações. Opackage-lock
foi adicionado em versões superiores ao do NPM 5.x.x, então se você está usando essa versão ou alguma maior, você o verá ser gerado, a não ser que você desabilite essa função.
O formato
Opackage-lock.json
é uma larga lista de dependências listadas no seupackage.json
, além de especificar a versão exata que deve ser instalado, a localização do módulo (URI), o hash que verifica a integridade do módulo e a lista de pacotes necessários. Vamos dar uma olhada nos registros presentes apenas para o express:
"express": {
"version": "4.15.4",
"resolved": "https://registry.npmjs.org/express/-/express-4.15.4.tgz",
"integrity": "sha1-Ay4iU0ic+PzgJma+yj0R7XotrtE=",
"requires": {
"accepts": "1.3.3",
"array-flatten": "1.1.1",
"content-disposition": "0.5.2",
"content-type": "1.0.2",
"cookie": "0.3.1",
"cookie-signature": "1.0.6",
"debug": "2.6.8",
"depd": "1.1.1",
"encodeurl": "1.0.1",
"escape-html": "1.0.3",
"etag": "1.8.0",
"finalhandler": "1.0.4",
"fresh": "0.5.0",
"merge-descriptors": "1.0.1",
"methods": "1.1.2",
"on-finished": "2.3.0",
"parseurl": "1.3.1",
"path-to-regexp": "0.1.7",
"proxy-addr": "1.1.5",
"qs": "6.5.0",
"range-parser": "1.2.0",
"send": "0.15.4",
"serve-static": "1.12.4",
"setprototypeof": "1.0.3",
"statuses": "1.3.1",
"type-is": "1.6.15",
"utils-merge": "1.0.0",
"vary": "1.1.1"
}
},
Entradas equivalentes podem ser encontradas para cada pacote listado na seção “requires”.
Então a ideia é que ao invés do NPM ler opackage.json
para instalar os módulos ele use opackage-lock.json
. Isso acontece justamente por conta do que disse anteriormente. Pelopackage-lock
especificar a versão, localização, hash para cada módulo, e suas dependências próprias, a instalação criada será sempre a mesma, toda vez. Não importa qual dispositivo você use, ou quando você fará a instalação, ele deverá ter o mesmo resultado, sempre, e isso é útil demais.
A controvérsia
Então, se opackage-lock.json
supostamente resolve um problema comum, por que os principais resultados de pesquisa (além da documentação do npm) são todos sobre desabilitá-lo ou questionar a função que ele desempenha?
Antes do NPM 5, opackage.json
era a fonte absoluta para qualquer projeto. O que estava nele era a lei. Os usuários do NPM gostaram desse modelo e se acostumaram a mantê-lo assim. Entretanto, quando opackage-lock
foi introduzido, ele agiu de forma contrária ao que as pessoas esperavam.
Dado um pacote preexistente e umpackage-lock
, uma alteração nopackage.json
(o que muitos usuários consideravam a fonte da verdade) não era refletida nopackage-lock
.
Exemplo: Pacote A, versão 1.0.0 nopackage
e nopackage-lock
. Nopackage.json
a versão A foi alterada manualmente para 1.1.0. Se um usuário considerar opackage.json
como a fonte da verdade e executar onpm install
, ele irá esperar que a versão 1.1.0 seja instalada. Entretanto, a versão 1.0.0 é instalada, apesar do fato de que a versão 1.1.0 está listada nopackage.json
.
Exemplo:Um módulo não existe nopackage-lock.json
, mas existe nopackage.json
. Como um usuário que olha para opackage.json
como a fonte de toda a verdade, eu esperaria que meu módulo fosse instalado. No entanto, como o módulo não está presente nopackage-lock.json
, ele não está instalado e meu código falha porque não consegue encontrar o módulo.
Na maior parte do tempo, porque a pessoa não conseguiu descobrir o motivo de suas dependências não estarem sendo instaladas corretamente, ela irá preferir remover opackage-lock.json
e rodar o comandoinstall
novamente, ou irá desabilitar sua criação.
O conflito entre o esperado e a realidade gerouuma discussão muito interessante no repositório do NPM. Algumas pessoas acham que opackage.json
deveria ser a fonte da verdade, outras acham que desde que o NPM considerou opackage-lock.json
como a fonte para realizar a instalação, essa deve ser a fonte real. A resolução desse conflito está noPR #17508.Os contribuidores do projeto adicionaram uma mudança aopackage.json
fazendo com que as regras presentes nele se sobrepujam ao que está nopackage-lock
.
Agora, em ambos cenários, os pacotes que os usuários esperam ser instalados, serão instalados corretamente. Essa mudança faz parte do release lançado na versão 5.1.0 do NPM, que foi ao ar em 5 julho de 2017.
Top comments (0)