
3 minutes read
npm ci vs. npm install: here's the difference
Table of contents
Introduction
If you’ve ever wondered whether to run npm ci
(which literally means clean install) or stick with good old npm install
, you’re in the right place. Here’s exactly what I learned.
What npm install
really does
When you run npm install
, here’s what’s happening:
- Semver resolution and lockfile updates: npm reads your
package.json
, figures out the latest acceptable versions based on semver ranges, and then checks against mypackage-lock.json
. If allowed ranges inpackage.json
mean newer versions are available, npm updates the lockfile accordingly. Since NPM 7, the lockfile typically takes priority. - Incremental node_modules mutation:
npm install
tries to save you time by only updating what’s necessary innode_modules
. This incremental approach is great for local development, especially with fast hot-reloading.
The npm ci
difference
But what about npm ci
? Here’s why it’s special:
- Lockfile-first philosophy:
npm ci
completely trusts the lockfile. No version guessing, no automatic upgrades. Just precise, byte-for-byte consistency. - The “nuke & pave” node_modules step: Every time you run
npm ci
, it wipes out the entirenode_modules
folder before rebuilding it exactly according to the lockfile. This ensures absolute cleanliness, though it can be slower locally if you already have an updated node_modules. - Strict sync checks: If my
package-lock.json
andpackage.json
aren’t perfectly synced (or if there’s no lockfile)npm ci
throws an error immediately.
When I reach for npm ci
(and when I don’t)
Here’s my personal rule-of-thumb:
- npm ci: Always in CI (Continuous Integration) pipelines, Docker builds, and production deployments. It ensures deterministic, fast, and predictable outcomes.
- npm install: Daily local development, especially when frequently adding or upgrading dependencies.
Common errors I still hit and quick fixes
Despite best practices, I still encounter occasional bumps:
- “package-lock.json is out of sync”: Quickly fix by running
npm install
(to regenerate lockfile) or, for a fresh environment,rm -rf node_modules && npm ci
. - Native add-ons rebuild loop: Mitigate by caching the entire npm cache directory (
~/.npm
) between builds. This avoids unnecessary rebuilds with node-gyp.
FAQ
Does npm ci
respect .npmrc proxies?
Yes, it fully respects npm configuration files. Note: per-project .npmrc
files override global .npmrc
.
Can I add a package with npm ci
?
Nope. Instead, use npm install lodash@latest
(or your desired package) and commit the updated lockfile.
Is pnpm still faster?
Usually, yes—but npm ci is plenty fast for most scenarios.
TL;DR
- Use
npm ci
for speed, consistency, and CI reliability. - Use
npm install
locally for flexibility and incremental updates. - Always commit and maintain a clean, synced
package-lock.json
.
Did you like this article? Then, keep learning:
- Understand incremental node_modules updates and dependency management nuances with npm install
- Learn to use Bun in Laravel projects to speed up frontend dependency management
- Explore fast and efficient package manager Bun as an alternative to npm
- Learn to use Bun in PHP projects for faster frontend dependency handling
- Discover how to disable annoying npm funding messages in your projects
- Explore how Laravel simplifies error handling, helpful for managing npm and build errors
- Discover tools and best practices to ensure security, relevant to reliable package management
0 comments