pnpm Performance Optimization
pnpm is fast by default, but these optimizations can make it even faster.
Install Optimizations
Use Frozen Lockfile
Skip resolution when lockfile exists:
pnpm install --frozen-lockfileThis is faster because pnpm skips the resolution phase entirely.
Prefer Offline Mode
Use cached packages when available:
pnpm install --prefer-offlineOr configure globally:
# .npmrc
prefer-offline=trueSkip Optional Dependencies
If you don't need optional deps:
pnpm install --no-optionalSkip Scripts
For CI or when scripts aren't needed:
pnpm install --ignore-scriptsCaution: Some packages require postinstall scripts to work correctly.
Only Build Specific Dependencies
Only run build scripts for specific packages:
# .npmrc
onlyBuiltDependencies[]=esbuild
onlyBuiltDependencies[]=sharp
onlyBuiltDependencies[]=@swc/coreOr skip builds entirely for deps that don't need them:
{
"pnpm": {
"neverBuiltDependencies": ["fsevents", "cpu-features"]
}
}Store Optimizations
Side Effects Cache
Cache native module build results:
# .npmrc
side-effects-cache=trueThis caches the results of postinstall scripts, speeding up subsequent installs.
Shared Store
Use a single store for all projects (default behavior):
# .npmrc
store-dir=~/.pnpm-storeBenefits:
- Packages downloaded once for all projects
- Hard links save disk space
- Faster installs from cache
Store Maintenance
Periodically clean unused packages:
# Remove unreferenced packages
pnpm store prune
# Check store integrity
pnpm store statusWorkspace Optimizations
Parallel Execution
Run workspace scripts in parallel:
pnpm -r --parallel run buildControl concurrency:
# .npmrc
workspace-concurrency=8Stream Output
See output in real-time:
pnpm -r --stream run buildFilter to Changed Packages
Only build what changed:
# Build packages changed since main branch
pnpm --filter "...[origin/main]" run buildTopological Order
Build dependencies before dependents:
pnpm -r run build
# Automatically runs in topological orderFor explicit sequential builds:
pnpm -r --workspace-concurrency=1 run buildNetwork Optimizations
Configure Registry
Use closest/fastest registry:
# .npmrc
registry=https://registry.npmmirror.com/HTTP Settings
Tune network settings:
# .npmrc
fetch-retries=3
fetch-retry-mintimeout=10000
fetch-retry-maxtimeout=60000
network-concurrency=16Proxy Configuration
# .npmrc
proxy=http://proxy.company.com:8080
https-proxy=http://proxy.company.com:8080Lockfile Optimization
Single Lockfile (Monorepos)
Use shared lockfile for all packages (default):
# .npmrc
shared-workspace-lockfile=trueBenefits:
- Single source of truth
- Faster resolution
- Consistent versions across workspace
Lockfile-only Mode
Only update lockfile without installing:
pnpm install --lockfile-onlyBenchmarking
Compare Install Times
# Clean install
rm -rf node_modules pnpm-lock.yaml
time pnpm install
# Cached install (with lockfile)
rm -rf node_modules
time pnpm install --frozen-lockfile
# With store cache
time pnpm install --frozen-lockfile --prefer-offlineProfile Resolution
Debug slow installs:
# Verbose logging
pnpm install --reporter=append-only
# Debug mode
DEBUG=pnpm:* pnpm installConfiguration Summary
Optimized .npmrc for performance:
# Install behavior
prefer-offline=true
auto-install-peers=true
# Build optimization
side-effects-cache=true
# Only build what's necessary
onlyBuiltDependencies[]=esbuild
onlyBuiltDependencies[]=@swc/core
# Network
fetch-retries=3
network-concurrency=16
# Workspace
workspace-concurrency=4Quick Reference
| Scenario | Command/Setting |
|---|---|
| CI installs | pnpm install --frozen-lockfile |
| Offline development | --prefer-offline |
| Skip native builds | neverBuiltDependencies |
| Parallel workspace | pnpm -r --parallel run build |
| Build changed only | pnpm --filter "...[origin/main]" build |
| Clean store | pnpm store prune |
<!-- Source references:
- https://pnpm.io/npmrc
- https://pnpm.io/cli/install
- https://pnpm.io/filtering
-->