Quite often, I have been asked the question “Why is package-lock.json always updated but never used as reference to stick the the packages it defines?”. Even though the answer is quite simple, it is not obvious enough. :)

The quick answer

package-lock.json is updated with every normal npm install to constantly reflect the packages that were used on the last build.

To use exactly the versions pinned in package-lock.json, one needs to use the npm ci command (npm docs). It’s called ci as this command is expected to be used primarily within CI systems / for builds executed in CI systems.

Thus, you should usually use npm ci instead of npm install in your build executed in CI jobs / pipelines.

Some background

npm-ci was introduced in March 2018 to provide faster, more reliable builds and a way for clean installs of your project based on a exact definition - the package-lock.json that is created and maintained on every regular npm install. Thus, the package-lock.json is intended to be pushed in your code repository and maintained along with your source code.


I hope this article clarifies the meaning of package-lock.json and how you can profit from it, especially if you’re not working exclusively in the context of NPM based projects.