O arquivo package-lock.json

Na versão 5, o npm introduziu o arquivo package-lock.json.

O que é isso? Você provavelmente conhece sobre o arquivo package.json, que é muito mais comum e está por aí a mais tempo.

O objeto do arquivo é manter rastreada a versão exata de cada pacote que está instalado, assim o produto é 100% reproduzível mesmo que pacotes sejam atualizados pelos seus mantenedores.

Isso resolve um problema muito específico que o package.json deixou para trás. No package.json você pode definir para quais versões você quer atualizar (patch ou minor), usando a notação semver, por exemplo:

  • se você especifica ~0.13.0, você quer atualizar apenas para versões patch: 0.13.1 está ok, mas 0.14.0 não está.
  • se você especifica ^0.13.0, você quer atualizar tanto para versões patch quanto minor: 0.13.1, 0.14.0 e assim por diante.
  • se você especifica 0.13.0, essa é a versão exata que será utilizada, sempre

Você não commita a pasta node_modules no seu Git, que geralmente é gigantesca, e quando você tenta replicar o projeto em outra máquina utilizando o comando npm install, se você especificou com a sintaxe ~ e uma versão patch do pacote foi lançada, ela que será instalada. O mesmo para ^ e versões inferiores.

Se você especifica versões exatas, como a 0.13.0 do exemplo, você não será afetado por esse problema.

Pode ser com você, ou com outra pessoa do outro lado do mundo tentando inicializar o projeto rodando npm install.

Então seu projeto original e o novo projeto recém inicializado são na verdade diferentes. Mesmo que uma versão patch ou minor não introduza mudanças que quebrem códigos antigos, nós todos sabemos que bugs podem (e vão) surgir.

O package-lock.json grava na pedra a exata versão instalada de cada pacote, e o npm vai utilizar essas exatas versões quando rodar npm install.

Esse conceito não é novo, e gerenciadores de pacotes de outras linguages (como o Composer no PHP) utilizam desse sistema por anos.

O arquivo package-lock.json precisa ser commitado no seu repositório Git, assim ele pode ser encontrado por outras pessoas, se o projeto é público ou você tem colaboradores, ou se você utiliza o GIT como fonte para deploys.

As versões das dependências vão ser atualizadas no arquivo package-lock.json quando você rodar npm update.

Um exemplo

Essa é uma estrutura de exemplo de um arquivo package-lock.json que é obtida quando rodamos npm install cowsay em uma pasta vazia:

{
"requires": true,
"lockfileVersion": 1,
"dependencies": {
"ansi-regex": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.
0.0.tgz",
"integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg="
},
"cowsay": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/cowsay/-/cowsay-1.3.1.tgz"
,
"integrity": "sha512-3PVFe6FePVtPj1HTeLin9v8WyLl+VmM1l1H/5P+BTTDkM
Ajufp+0F9eLjzRnOHzVAYeIYFF5po5NjRrgefnRMQ==",
"requires": {
"get-stdin": "^5.0.1",
"optimist": "~0.6.1",
"string-width": "~2.1.1",
"strip-eof": "^1.0.0"
}
},
"get-stdin": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-5.0.
1.tgz",
"integrity": "sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g="
},
"is-fullwidth-code-point": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/
is-fullwidth-code-point-2.0.0.tgz",
"integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="
},
"minimist": {
"version": "0.0.10",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10
.tgz",
"integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8="
},
"optimist": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz",
"integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=",
"requires": {
"minimist": "~0.0.1",
"wordwrap": "~0.0.2"
}
},
"string-width": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
"integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
"requires": {
"is-fullwidth-code-point": "^2.0.0",
"strip-ansi": "^4.0.0"
}
},
"strip-ansi": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
"integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
"requires": {
"ansi-regex": "^3.0.0"
}
},
"strip-eof": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
"integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8="
},
"wordwrap": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz",
"integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc="
}
}
}

Nós instalamos o cowsay, que depende de:

  • get-stdin
  • optimist
  • string-width
  • strip-eof

Por sua vez, esses pacotes dependem de outros pacotes, como podemos ver nos requires de alguns deles:

  • ansi-regex
  • is-fullwidth-code-point
  • minimist
  • wordwrap
  • strip-eof

Eles são adicionados ao arquivo em ordem alfabética, e cada um têm um campo version, um resolver, que aponta para a localização do pacote, e um integrity, que é uma string para validação do pacote.