DEV Community

Cover image for PNPM: Beyond Dependency Management - A Modern Alternative to NVM
Ítalo Queiroz
Ítalo Queiroz

Posted on

PNPM: Beyond Dependency Management - A Modern Alternative to NVM

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
Enter fullscreen mode Exit fullscreen mode

Uninstalling Node.js (if globally installed)

macOS (via Homebrew)

brew uninstall node
brew uninstall npm
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Verifying the Cleanup

# These commands should return "command not found"
node --version
npm --version
nvm --version
Enter fullscreen mode Exit fullscreen mode

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 -
Enter fullscreen mode Exit fullscreen mode

Via wget (Alternative)

wget -qO- https://get.pnpm.io/install.sh | sh -
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Verifying the Installation

# Check if pnpm was installed correctly
pnpm --version

# Check location
which pnpm
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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"
}
Enter fullscreen mode Exit fullscreen mode

.pnpmrc Configuration

To further optimize pnpm usage, you can create a global .pnpmrc file:

# Create global configuration file
touch ~/.pnpmrc
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Potential Limitations

It's important to be aware of some limitations:

  1. Adoption: Smaller user base compared to nvm
  2. Documentation: Fewer online resources about Node.js management
  3. Shell Scripts: Some scripts may assume nvm usage
  4. Integration: Some tools may not automatically recognize
  5. 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)