Commit the lockfile and run npm ci in CI and deploys. A lockfile records the exact versions installed, and npm ci installs only those, failing if package.json and the lockfile disagree. That makes a client build repeatable and stops a new upstream release from slipping in unreviewed.
What a lockfile does
Your package.json usually allows ranges, such as any compatible minor version. The lockfile records the exact versions chosen, including transitive packages that you never wrote down. Two developers running a plain install a week apart can get different trees if nothing is committed.
For an agency this matters twice. You build the same project on several laptops and in CI, and a client will later rebuild it without you.
npm install versus npm ci
The npm documentation lists the differences. The project must already have a package-lock.json or npm-shrinkwrap.json. If dependencies in the lock do not match package.json, npm ci exits with an error instead of updating the lock. It removes any existing node_modules first and never writes to package.json or the lock. Installs are, in the docs' words, essentially frozen.
| Question | npm install | npm ci |
|---|---|---|
| Needs a lockfile | No | Yes |
| Can change the lockfile | Yes | No |
| Fails on mismatch | No | Yes |
| Good for | Adding or updating packages | CI, deploys, client rebuilds |
Steps to set it up
- Commit package-lock.json. Do not add it to .gitignore.
- Change CI and Docker builds from npm install to npm ci.
- Add a CI check that fails if the lockfile changes during the build.
- Make lockfile changes reviewable. Require a pull request, and look at the lockfile diff when a dependency bump lands.
- Record the Node and npm versions in the repo, since the docs note that flags used when creating the lock, such as legacy peer deps, must be repeated for npm ci.
# in CI and Dockerfile
npm ci
What a lockfile does not do
It does not make a dependency safe. If a vulnerable or malicious version is locked, npm ci will faithfully install it. It also does not verify who published a package. Pair it with advisory checks, and review diffs when versions change.
It also freezes you in place. Old lockfiles are how client sites end up on packages with known flaws, so schedule updates rather than hoping for them.
Try it yourself
Click through it at your own pace, or open it full screen.
Open the inventory and compare the number of direct packages with the total. The gap is what the lockfile is pinning for you.
Quick check
Should a library commit its lockfile?
Applications and client deliverables should. For published libraries the practice differs, because consumers resolve their own trees. Agencies mostly ship applications, so commit it.
Does npm ci replace npm audit?
No. npm ci makes installs repeatable. npm audit checks the locked versions against known advisories. Use both.
Sources
Last reviewed: 19 October 2026.