pnpm (performant npm) has already won over many developers with its efficiency in dependency management, but did you know it can also replace NVM for managing your Node.js versions? In this post, I'll show you how I use pnpm as a complete solution for my projects.
Why Consider PNPM?
Before diving into Node.js version management, let's recap the benefits of pnpm:
- Space efficiency: Uses hard links and symbolic links to avoid package duplication
- Speed: Faster installations than npm and yarn
- Compatibility: Works with existing npm projects
- Monorepos: Native and efficient workspace support
⚠️ Preparing the Environment: Necessary Cleanup
Important: To avoid conflicts and ensure a clean experience, I strongly recommend uninstalling NVM and Node.js before installing pnpm.
Uninstalling NVM
# 1. Remove the nvm directory
rm -rf ~/.nvm
# 2. Clean shell configurations
# Edit your ~/.bashrc, ~/.zshrc, ~/.profile and remove these lines:
# export NVM_DIR="$HOME/.nvm"
# [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
# [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"
# 3. Reload the shell
source ~/.zshrc # or ~/.bashrc
Uninstalling Node.js (if globally installed)
macOS (via Homebrew)
brew uninstall node
brew uninstall npm
macOS (manual installation)
# Remove Node.js
sudo rm -rf /usr/local/{bin/{node,npm},lib/node_modules/npm,lib/node,share/man/*/node.*}
# Clean cache
sudo rm -rf ~/.npm
Linux (Ubuntu/Debian)
# If installed via apt
sudo apt remove nodejs npm
# If installed via snap
sudo snap remove node
# Clean remaining files
sudo rm -rf /usr/local/bin/npm
sudo rm -rf /usr/local/share/man/man1/node*
sudo rm -rf /usr/local/lib/dtrace/node.d
sudo rm -rf ~/.npm
sudo rm -rf ~/.node-gyp
Verifying the Cleanup
# These commands should return "command not found"
node --version
npm --version
nvm --version
Installing PNPM
Recommendation: Use only curl or wget installation for a clean and controlled setup:
Via cURL (Recommended)
curl -fsSL https://get.pnpm.io/install.sh | sh -
Via wget (Alternative)
wget -qO- https://get.pnpm.io/install.sh | sh -
Configuring the PATH
After installation, add pnpm to your PATH:
# For zsh
echo 'export PATH="$HOME/.local/share/pnpm:$PATH"' >> ~/.zshrc
# For bash
echo 'export PATH="$HOME/.local/share/pnpm:$PATH"' >> ~/.bashrc
# Reload the shell
source ~/.zshrc # or ~/.bashrc
Verifying the Installation
# Check if pnpm was installed correctly
pnpm --version
# Check location
which pnpm
Managing Node.js Versions with PNPM
Installing a Specific Version
pnpm offers commands similar to nvm for managing Node.js versions:
# Install the latest LTS version (20.x)
pnpm env use --global lts
# Install a specific version
pnpm env use --global 20.11.1
# Install the latest version (21.x)
pnpm env use --global latest
# Install a specific newer version
pnpm env use --global 21.7.3
Listing Available and Installed Versions
# View available remote versions
pnpm env list --remote
# View locally installed versions
pnpm env list
# View only remote LTS versions (20.x)
pnpm env list --remote lts
Using Versions per Project
One of the most interesting features is defining Node.js version per project:
# In your project directory
pnpm env use 20.11.1
# For projects that need newer features
pnpm env use 21.7.3
You can also specify the version in package.json
:
{
"name": "my-project",
"engines": {
"node": "20.11.1",
"pnpm": "8.15.0"
},
"packageManager": "pnpm@8.15.0"
}
.pnpmrc Configuration
To further optimize pnpm usage, you can create a global .pnpmrc
file:
# Create global configuration file
touch ~/.pnpmrc
Some useful configurations:
# ~/.pnpmrc
# Auto-install peer dependencies
auto-install-peers=true
# Use hard links when possible
use-node-version=20.11.1
# Configure global store
store-dir=~/.pnpm-store
# Enable hoisting for compatibility
hoist=true
shamefully-hoist=false
Complete Workflow: New Project
Here's my typical workflow for starting a new project after migration:
# 1. Check if pnpm is working
pnpm --version
# 2. Create project directory
mkdir my-new-project && cd my-new-project
# 3. Set Node.js version for the project (current LTS)
pnpm env use 20.11.1
# 4. Verify Node.js was installed correctly
node --version # Should show v20.11.1
npm --version
# 5. Initialize project
pnpm init
# 6. Install dependencies
pnpm add react react-dom
pnpm add -D typescript @types/react @types/react-dom
Useful Daily Commands
# Switch between versions globally
pnpm env use --global 20.11.1
pnpm env use --global 21.7.3
# For projects needing experimental features
pnpm env use --global 22.0.0
# Remove an installed version
pnpm env remove --global 20.10.0
# See which version is active
pnpm env list
# Update pnpm
pnpm add -g pnpm
Comparison: PNPM vs NVM
Aspect | PNPM | NVM |
---|---|---|
Node.js Management | ✅ Yes | ✅ Yes |
Dependency Management | ✅ Excellent | ❌ No |
Performance | ✅ Very fast | ⚠️ Moderate |
Space Efficiency | ✅ Yes | ❌ No |
Compatibility | ✅ Full | ✅ Full |
Per-Project Configuration | ✅ Native | ⚠️ Requires .nvmrc |
Learning Curve | ⚠️ Moderate | ✅ Simple |
Installation Conflicts | ✅ Minimal | ⚠️ Can occur |
Tips and Tricks
1. Script for Automatic Version Switching
Create a script that automatically uses the correct version based on package.json
:
# .zshrc or .bashrc
pnpm-auto() {
if [[ -f package.json ]]; then
local node_version=$(node -p "require('./package.json').engines?.node || '20.11.1'")
pnpm env use $node_version
fi
}
# Usage: pnpm-auto
2. Useful Aliases
# .zshrc or .bashrc
alias pn="pnpm"
alias pni="pnpm install"
alias pna="pnpm add"
alias pnr="pnpm run"
alias pnu="pnpm update"
alias pnv="pnpm env list"
alias pn20="pnpm env use 20.11.1"
alias pn21="pnpm env use 21.7.3"
3. Multi-Project Configuration Example
For different project types, you can have specific configurations:
# Modern React/Next.js project
pnpm env use 20.11.1
# Experimental project with edge features
pnpm env use 21.7.3
# Project needing latest features
pnpm env use latest
Potential Limitations
It's important to be aware of some limitations:
- Adoption: Smaller user base compared to nvm
- Documentation: Fewer online resources about Node.js management
- Shell Scripts: Some scripts may assume nvm usage
- Integration: Some tools may not automatically recognize
- Very recent versions: Some bleeding-edge versions may take time to become available
Conclusion
pnpm has proven to be a versatile tool that goes beyond simple dependency management. For developers seeking a unified and performant solution, the complete migration from NVM to pnpm is a decision that significantly simplifies the development toolkit.
The combination of speed, space efficiency, and integrated functionality, along with a clean installation without conflicts, makes pnpm a modern and efficient alternative to the traditional npm + nvm combo.
Top comments (0)