본문으로 건너뛰기 pnpm Complete Guide

pnpm Complete Guide

pnpm Complete Guide

이 글의 핵심

pnpm is a fast, disk space efficient package manager for Node.js. It uses a content-addressable store to save disk space and is up to 3x faster than npm.

Introduction

pnpm (performant npm) is a fast, disk space efficient package manager. It solves npm’s performance and disk space issues by using a global content-addressable store.

The Problem with npm

npm/yarn:

# Each project duplicates node_modules
project1/node_modules/lodash  # 2MB
project2/node_modules/lodash  # 2MB
project3/node_modules/lodash  # 2MB
# Total: 6MB for 3 projects

pnpm:

# One copy in global store, hard links in projects
~/.pnpm-store/lodash          # 2MB (once)
project1/node_modules/lodash  # hard link (0 bytes)
project2/node_modules/lodash  # hard link (0 bytes)
project3/node_modules/lodash  # hard link (0 bytes)
# Total: 2MB for 3 projects

1. Installation

# Via npm
npm install -g pnpm

# Via standalone script (recommended)
curl -fsSL https://get.pnpm.io/install.sh | sh -

# Via Homebrew (macOS)
brew install pnpm

# Via Volta
volta install pnpm

Verify installation:

pnpm --version

2. Basic Commands

Install Dependencies

# Install all dependencies
pnpm install

# Add a dependency
pnpm add express

# Add dev dependency
pnpm add -D typescript

# Add global package
pnpm add -g pm2

Remove Dependencies

# Remove package
pnpm remove express

# Remove dev dependency
pnpm remove -D typescript

Update Dependencies

# Update all dependencies
pnpm update

# Update specific package
pnpm update express

# Update to latest (ignore semver)
pnpm update express --latest

3. Speed Comparison

Commandnpmyarnpnpm
Install51s37s16s
Install (cache)33s11s1.5s
Install (lockfile)28s11s5s

pnpm is 2-3x faster!

4. Disk Space Efficiency

# Check disk usage
pnpm store status

# Example output:
# Content-addressable store is at: ~/.pnpm-store
# Total size: 2.5 GB
# Projects using store: 47
# Equivalent npm size: ~15 GB (saved 12.5 GB!)

5. Workspaces (Monorepo)

Setup

# pnpm-workspace.yaml
packages:
  - 'packages/*'
  - 'apps/*'

Project structure:

monorepo/
├── pnpm-workspace.yaml
├── package.json
├── packages/
│   ├── ui/
│   │   └── package.json
│   └── utils/
│       └── package.json
└── apps/
    ├── web/
    │   └── package.json
    └── api/
        └── package.json

Install Dependencies

# Install all workspace dependencies
pnpm install

# Install for specific package
pnpm --filter web add react

# Install for all packages
pnpm -r add lodash

Run Scripts

# Run script in specific package
pnpm --filter web dev

# Run in all packages
pnpm -r build

# Run in parallel
pnpm -r --parallel test

6. Filtering

# Install dependencies for 'web' package
pnpm --filter web install

# Run build for all packages in 'packages' folder
pnpm --filter './packages/*' build

# Run dev for 'web' and its dependencies
pnpm --filter web... dev

# Run build for packages that depend on 'utils'
pnpm --filter ...utils build

7. Scripts

// package.json
{
  "scripts": {
    "dev": "pnpm --filter web dev",
    "build": "pnpm -r build",
    "test": "pnpm -r --parallel test",
    "clean": "pnpm -r exec rm -rf dist"
  }
}

8. Configuration

# .npmrc
# Store location
store-dir=~/.pnpm-store

# Symlink node_modules
node-linker=hoisted

# Strict peer dependencies
strict-peer-dependencies=true

# Auto install peer dependencies
auto-install-peers=true

# Shamefully hoist (for compatibility)
shamefully-hoist=false

# Lockfile location
lockfile=true

9. Migration from npm/yarn

Step 1: Remove old files

rm -rf node_modules package-lock.json yarn.lock

Step 2: Install with pnpm

pnpm install

Step 3: Update CI/CD

# GitHub Actions
- uses: pnpm/action-setup@v2
  with:
    version: 8

- uses: actions/setup-node@v3
  with:
    node-version: 18
    cache: 'pnpm'

- run: pnpm install
- run: pnpm build

10. Real-World Example: Next.js Monorepo

Structure:

nextjs-monorepo/
├── pnpm-workspace.yaml
├── package.json
├── apps/
│   ├── web/
│   │   ├── package.json
│   │   └── next.config.js
│   └── admin/
│       ├── package.json
│       └── next.config.js
└── packages/
    ├── ui/
    │   ├── package.json
    │   └── src/
    └── config/
        └── package.json

pnpm-workspace.yaml:

packages:
  - 'apps/*'
  - 'packages/*'

Root package.json:

{
  "name": "nextjs-monorepo",
  "private": true,
  "scripts": {
    "dev": "pnpm --filter web dev",
    "dev:admin": "pnpm --filter admin dev",
    "build": "pnpm -r build",
    "lint": "pnpm -r lint",
    "test": "pnpm -r test"
  },
  "devDependencies": {
    "typescript": "^5.0.0",
    "eslint": "^8.0.0"
  }
}

apps/web/package.json:

{
  "name": "web",
  "version": "1.0.0",
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start"
  },
  "dependencies": {
    "next": "^14.0.0",
    "react": "^18.0.0",
    "ui": "workspace:*"
  }
}

packages/ui/package.json:

{
  "name": "ui",
  "version": "1.0.0",
  "main": "./src/index.ts",
  "types": "./src/index.ts",
  "dependencies": {
    "react": "^18.0.0"
  }
}

11. Advanced Features

Patching Packages

# Create patch
pnpm patch lodash@4.17.21

# Edit files in temporary directory
# Save and generate patch
pnpm patch-commit /tmp/patch-123

# Patch is saved to patches/lodash@4.17.21.patch

Overrides

// package.json
{
  "pnpm": {
    "overrides": {
      "axios": "1.0.0",
      "react@<18.0.0": "18.0.0"
    }
  }
}

Catalog

# pnpm-workspace.yaml
catalog:
  react: ^18.0.0
  typescript: ^5.0.0
// package.json
{
  "dependencies": {
    "react": "catalog:"
  }
}

12. Docker Integration

# Dockerfile
FROM node:18-alpine

# Install pnpm
RUN corepack enable && corepack prepare pnpm@latest --activate

WORKDIR /app

# Copy workspace files
COPY pnpm-lock.yaml pnpm-workspace.yaml ./
COPY package.json ./

# Install dependencies
RUN pnpm install --frozen-lockfile

# Copy source
COPY . .

# Build
RUN pnpm build

CMD ["pnpm", "start"]

With layer caching:

FROM node:18-alpine AS deps
RUN corepack enable && corepack prepare pnpm@latest --activate

WORKDIR /app
COPY pnpm-lock.yaml package.json ./
RUN pnpm install --frozen-lockfile --prod

FROM node:18-alpine AS builder
RUN corepack enable && corepack prepare pnpm@latest --activate

WORKDIR /app
COPY pnpm-lock.yaml package.json ./
RUN pnpm install --frozen-lockfile

COPY . .
RUN pnpm build

FROM node:18-alpine AS runner
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY --from=builder /app/dist ./dist
COPY package.json ./

CMD ["node", "dist/index.js"]

13. Troubleshooting

Problem: Peer dependency warnings

# Auto install peer dependencies
pnpm add --save-peer react-dom

# Or configure .npmrc
echo "auto-install-peers=true" >> .npmrc

Problem: Module not found

# Use shamefully-hoist for compatibility
echo "shamefully-hoist=true" >> .npmrc
pnpm install

Problem: Slow installation

# Clear cache
pnpm store prune

# Use faster mirror (China)
pnpm config set registry https://registry.npmmirror.com

14. Best Practices

1. Use workspace protocol

{
  "dependencies": {
    "ui": "workspace:*"  // Any version from workspace
  }
}

2. Pin pnpm version

// package.json
{
  "packageManager": "pnpm@8.15.0"
}

3. Use .npmrc for team settings

# .npmrc
auto-install-peers=true
strict-peer-dependencies=false
shamefully-hoist=false

4. Commit pnpm-lock.yaml

git add pnpm-lock.yaml
git commit -m "chore: update dependencies"

15. Performance Tips

1. Use frozen lockfile in CI

pnpm install --frozen-lockfile

2. Prune store regularly

pnpm store prune

3. Use offline mode

pnpm install --offline

Summary

pnpm revolutionizes Node.js package management:

  • 3x faster than npm
  • Saves disk space with content-addressable store
  • Monorepo support with workspaces
  • 100% compatible with npm packages
  • Strict by default prevents phantom dependencies

Key Takeaways:

  1. Uses hard links to save disk space
  2. 2-3x faster than npm/yarn
  3. Built-in monorepo support
  4. Compatible with all npm packages
  5. Strict dependency resolution

Next Steps:

Resources:


Frequently Asked Questions (FAQ)

Q. When would I use this in practice?

A. Complete pnpm guide for Node.js package management. Learn installation, workspaces, monorepo setup, and why pnpm is 3x f…

Q. What should I read before this?

A. Follow the previous article or related articles links at the bottom of each post to learn in sequence.

Q. Where can I study this more deeply?

A. Check cppreference and the relevant library’s official documentation. The reference links at the end of the article are also worth using.


Other articles related to this topic.


Keywords Covered in This Article (Related Search Terms)

This article covers pnpm, Package Manager, Node.js, JavaScript, Monorepo, DevOps.