
3 minutes read
npm ci vs. npm install or reliability vs. speed
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, usenpm 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