Back to Blog
pnpmnpmPackage ManagerNode.js

Why Choose pnpm for Package Management

Explore pnpm benefits. From faster installs to disk space savings to monorepo support.

B
Bootspring Team
Engineering
July 23, 2021
5 min read

pnpm offers faster installs and better disk usage. Here's why you should consider switching.

Key Benefits#

1# Install pnpm 2npm install -g pnpm 3 4# Or with corepack 5corepack enable 6corepack prepare pnpm@latest --activate 7 8# Check version 9pnpm --version

Content-Addressable Storage#

Traditional npm: project-a/node_modules/lodash/ project-b/node_modules/lodash/ project-c/node_modules/lodash/ # 3 copies of lodash pnpm: ~/.pnpm-store/ lodash@4.17.21/ # Single copy project-a/node_modules/.pnpm/lodash@4.17.21 project-b/node_modules/.pnpm/lodash@4.17.21 project-c/node_modules/.pnpm/lodash@4.17.21 # All symlinked to store
1# View store stats 2pnpm store status 3 4# Prune unused packages 5pnpm store prune 6 7# Check disk usage 8du -sh ~/.pnpm-store

Strict Node Modules#

1// npm allows accessing undeclared dependencies (hoisting) 2// This works with npm but shouldn't: 3import something from 'transitive-dep'; // Not in package.json 4 5// pnpm enforces strict mode 6// You can only import declared dependencies 7// This prevents phantom dependencies
# If you need hoisting (legacy compatibility) # .npmrc node-linker=hoisted shamefully-hoist=true

Common Commands#

1# Install all dependencies 2pnpm install 3pnpm i 4 5# Add dependency 6pnpm add lodash 7pnpm add -D typescript # Dev dependency 8pnpm add -O webpack # Optional dependency 9pnpm add lodash@4.17.21 # Specific version 10 11# Remove dependency 12pnpm remove lodash 13pnpm rm lodash 14 15# Update dependencies 16pnpm update 17pnpm up lodash # Update specific 18pnpm up --latest # Update to latest (ignoring semver) 19 20# Run scripts 21pnpm run build 22pnpm build # Shorthand 23 24# Execute package binary 25pnpm exec tsc 26pnpm dlx create-react-app # Like npx

Lockfile#

1# pnpm-lock.yaml (more readable than package-lock.json) 2lockfileVersion: '9.0' 3 4settings: 5 autoInstallPeers: true 6 7importers: 8 .: 9 dependencies: 10 react: 11 specifier: ^18.2.0 12 version: 18.2.0 13 14packages: 15 react@18.2.0: 16 resolution: {integrity: sha512-...} 17 engines: {node: '>=0.10.0'}

Workspaces (Monorepo)#

# pnpm-workspace.yaml packages: - 'packages/*' - 'apps/*' - '!**/test/**'
1# Install all workspace dependencies 2pnpm install 3 4# Run command in specific package 5pnpm --filter @myorg/web build 6pnpm -F @myorg/web build 7 8# Run command in all packages 9pnpm -r build 10pnpm --recursive build 11 12# Run command in packages that changed 13pnpm -F '...[origin/main]' build 14 15# Add dependency to workspace package 16pnpm add lodash --filter @myorg/utils 17 18# Add workspace package as dependency 19pnpm add @myorg/utils --filter @myorg/web --workspace
1// packages/web/package.json 2{ 3 "name": "@myorg/web", 4 "dependencies": { 5 "@myorg/utils": "workspace:*" 6 } 7}

Performance Comparison#

1# Benchmark (typical results) 2# Clean install: 3npm install # ~45 seconds 4yarn install # ~35 seconds 5pnpm install # ~15 seconds 6 7# With cache: 8npm install # ~20 seconds 9yarn install # ~10 seconds 10pnpm install # ~5 seconds 11 12# Disk usage (10 similar projects): 13npm # ~2.5 GB 14yarn # ~2.5 GB 15pnpm # ~500 MB (shared store)

Configuration#

1# .npmrc 2# Strict peer dependencies 3auto-install-peers=true 4strict-peer-dependencies=true 5 6# Use specific store location 7store-dir=~/.pnpm-store 8 9# Prefer offline 10prefer-offline=true 11 12# Registry 13registry=https://registry.npmjs.org/ 14 15# Workspace settings 16link-workspace-packages=true 17shared-workspace-lockfile=true

Scripts and Hooks#

1// package.json 2{ 3 "scripts": { 4 "preinstall": "npx only-allow pnpm", 5 "prepare": "husky install" 6 }, 7 "packageManager": "pnpm@8.15.0" 8}
# Run pre/post hooks pnpm run prebuild # Runs before build pnpm run build pnpm run postbuild # Runs after build

Overrides and Patches#

1// package.json 2{ 3 "pnpm": { 4 "overrides": { 5 "lodash": "4.17.21", 6 "foo@^1.0.0>bar": "2.0.0" 7 }, 8 "patchedDependencies": { 9 "some-package@1.0.0": "patches/some-package.patch" 10 } 11 } 12}
# Create patch pnpm patch some-package@1.0.0 # Edit files in temporary directory pnpm patch-commit <path>

CI/CD Setup#

1# GitHub Actions 2name: CI 3 4on: [push, pull_request] 5 6jobs: 7 build: 8 runs-on: ubuntu-latest 9 10 steps: 11 - uses: actions/checkout@v4 12 13 - uses: pnpm/action-setup@v3 14 with: 15 version: 8 16 17 - uses: actions/setup-node@v4 18 with: 19 node-version: 20 20 cache: 'pnpm' 21 22 - run: pnpm install --frozen-lockfile 23 - run: pnpm build 24 - run: pnpm test
1# Dockerfile 2FROM node:20-alpine 3 4RUN corepack enable 5 6WORKDIR /app 7 8COPY pnpm-lock.yaml package.json ./ 9RUN pnpm install --frozen-lockfile --prod 10 11COPY . . 12RUN pnpm build 13 14CMD ["node", "dist/index.js"]

Migration from npm/yarn#

1# Import from package-lock.json 2pnpm import 3 4# Remove npm/yarn files 5rm -rf node_modules package-lock.json yarn.lock 6 7# Install with pnpm 8pnpm install 9 10# Verify 11pnpm ls

Troubleshooting#

1# Clear cache 2pnpm store prune 3 4# Rebuild node_modules 5rm -rf node_modules 6pnpm install 7 8# Check for issues 9pnpm why lodash # Why is package installed 10pnpm ls --depth 2 # List dependencies 11pnpm outdated # Check for updates 12 13# Verify store integrity 14pnpm store verify

Best Practices#

Project Setup: ✓ Add packageManager to package.json ✓ Use preinstall to enforce pnpm ✓ Commit pnpm-lock.yaml ✓ Configure .npmrc for team Performance: ✓ Use --frozen-lockfile in CI ✓ Enable prefer-offline ✓ Prune store periodically ✓ Use workspace protocol Monorepos: ✓ Define pnpm-workspace.yaml ✓ Use workspace: protocol ✓ Filter commands appropriately ✓ Share common configurations

Conclusion#

pnpm provides faster installs, better disk usage, and stricter dependency management. Its content-addressable store eliminates duplication, while strict mode prevents phantom dependencies. For monorepos, workspace support makes it an excellent choice for managing multiple packages.

Share this article

Help spread the word about Bootspring