Working with multiple Node.js projects often means switching between different Node versions, reinstalling dependencies and remembering various nvm and npm commands. This becomes especially painful when moving between legacy and modern codebases.
This article provides a practical overview of my most common Node.js workflow tasks: switching Node versions using nvm, cleaning and reinstalling dependencies and using the correct npm installation strategy for local development and CI/CD environments.
If you regularly jump between projects and forget the exact commands, this guide provides a simple, repeatable workflow you can reuse every day.
Contents
Switching to a Different Node Version
First, determine which Node version the project requires.
Check the required version
package.json declares supported Node versions:
{
"engines": {
"node": ">=18"
}
}
Use the terminal to verify which Node.js version is active locally:
node -v
# or
node --version
Once you know which version is required, list locally installed Node
versions:
nvm ls
If the required version is not installed locally:
nvm install <version>
Then switch to the desired version:
nvm use <version>
.nvmrc approach
Instead of manually checking the required Node version in package.json, you can define it using an .nvmrc file.
The file contains only the Node version:
18.19.0
Once the file exists, switching versions becomes simpler:
nvm use
Running nvm use inside a directory containing .nvmrc switches to the specified version. Automatic switching requires shell integration (e.g., zsh hooks or tools like avn).
.nvmrc vs package.json
package.json and .nvmrc solve related but different problems:
- the
enginesfield inpackage.jsondeclares supported Node versions -
.nvmrcallowsnvmto automatically switch the runtime version
Using both helps keep development environments consistent across projects and teams.
Clean and Reinstall Dependencies
There are two main approaches to cleaning and reinstalling dependencies, depending on whether you want to preserve exact versions or update them:
-
Reinstall with locked versions – Reinstalls
node_moduleswhile keeping the exact versions specified inpackage-lock.json. This approach is recommended for teams and CI/CD environments, as it ensures reproducible builds. -
Full reinstall – Removes
node_modulesandpackage-lock.jsonbefore reinstalling all dependencies. This is useful when performing major dependency upgrades or resolving inconsistencies in the dependency graph.
Before diving into the commands, here’s a quick table summarizing when to use each strategy:
Installation Strategy Comparison
| Scenario | Command | Lockfile Behavior |
|---|---|---|
| Standard CI/CD Build | npm ci |
Unchanged (strictly enforced) |
| Team Development | npm ci |
Unchanged (strictly enforced) |
| Maintenance / Updates | npm install |
Updates within semver; rewrites lockfile |
| Full Reset | rm -rf node_modules package-lock.json && npm install |
Fully regenerated |
Reinstall with locked versions
This approach is preferred for teams and CI/CD pipelines because it preserves exact dependency versions:
npm ci
Why npm ci?
- installs exact versions from
package-lock.json - produces reproducible builds
- faster and deterministic installs
- preferred for teams and CI environments
- removes
node_modules
Note
npm cifails ifpackage.jsonandpackage-lock.jsonare out of sync, preventing accidental dependency drift.
Full reinstall
Full reinstall is useful when performing major dependency upgrades, switching Node versions or resolving dependency graph inconsistencies.
# Unix/Bash
rm -rf node_modules && rm package-lock.json && npm i
To completely reinstall dependencies, remove node_modules and package-lock.json, then run npm install. This regenerates package-lock.json, so review the changes carefully before committing them to Git to keep dependencies consistent across the team and CI environments.
In team settings, avoid deleting package-lock.json casually, as it updates the entire dependency graph for everyone working on the project.
rm -rf node_modules
Removes the node_modules directory recursively.
Why delete node_modules?
It may contain:
- corrupted installs
- incompatible binaries
- dependency conflicts
- leftover versions after upgrades
- OS‑specific builds
Removing it forces a clean rebuild.
rm package-lock.json
Deletes the lock file and forces a fresh dependency resolution.
Why remove it?
- recompute dependency versions
- resolve a new dependency graph
- potentially upgrade sub-dependencies
Note: Deleting
package-lock.jsontriggers a "fresh" resolution of all sub-dependencies. Only do this if you intend to update your entire dependency tree.
npm i (npm install)
This command:
- reads
package.json - resolves dependencies
- downloads packages
- creates a new
node_modulesdirectory - generates a new
package-lock.json
Corrupted npm Cache
In rare cases, npm installs may fail due to a corrupted local cache. Typical symptoms include integrity errors, failed package extraction, or repeated installation failures.
Verify the cache (recommended first step)
npm cache verify
This checks the cache integrity and removes invalid entries automatically.
Clean the cache
If problems persist, you can clear the npm cache:
npm cache clean --force
The --force flag is required because npm protects the cache by default. After cleaning the cache, run npm install again to rebuild dependencies.
Note Clearing the cache is rarely necessary and should only be used when troubleshooting installation issues. The npm cache is stored in
~/.npm(Linux/macOS) or%AppData%/npm-cache(Windows).
In modern npm versions (v7+), cache corruption is uncommon because npm performs strict integrity verification and automatically removes invalid cache entries.
Change registry
In some environments especially when working with private packages or company infrastructure, you may need to configure npm to use a custom registry. This is typically done once when setting up a development machine.
Log in to a registry
Authenticate against a custom registry:
npm login --registry=<registry-url> --auth-type=web
This stores authentication credentials (usually as an auth token) in your local npm configuration.
Set the default registry
Configure npm to use a specific registry by default:
npm config set registry <registry-url>
This updates your user-level npm configuration.
You can verify the current registry with:
npm config get registry
Show current npm configuration
Display the active npm configuration:
npm config list
This shows configuration values from all scopes (global, user, and project).
Note Some projects define a registry inside a project-level .npmrc, which overrides global settings.
Top comments (0)