Bỏ qua để vào nội dung chính
pnpm Workspaces: The Developer's Guide to Efficient Monorepo Package Management

pnpm Workspaces: The Developer's Guide to Efficient Monorepo Package Management

Bởi James Rivera
24 thg 3, 20267 phút đọc

pnpm workspaces use symlinks and a content-addressable store to save disk space and speed up installs. Learn workspace protocols, filtering, and sharing packages across your monorepo.

Why pnpm Over npm and yarn for Monorepos

pnpm uses a content-addressable store on disk: every version of every package is stored once, and workspaces link to it via symlinks. On a monorepo with 10 apps sharing React, React is stored once — not 10 times. This saves gigabytes of disk space and makes installs dramatically faster.

Setting Up pnpm Workspaces

# pnpm-workspace.yaml
packages:
  - 'apps/*'
  - 'packages/*'
  - 'tools/*'
// Root package.json
{
  "name": "my-monorepo",
  "private": true,
  "engines": { "pnpm": ">=9.0.0" },
  "scripts": {
    "dev": "turbo dev",
    "build": "turbo build",
    "lint": "turbo lint",
    "format": "biome check --write ."
  }
}

The workspace: Protocol

The workspace: protocol ensures packages link to local versions rather than npm:

// apps/web/package.json
{
  "dependencies": {
    "@repo/ui": "workspace:*",
    "@repo/utils": "workspace:*",
    "@repo/config": "workspace:^1.0.0"
  }
}

workspace:* means "any version from the workspace" — it always uses the local package. workspace:^1.0.0 applies semver constraints within the workspace.

Filtering Commands to Specific Packages

# Run a command in a specific package
pnpm --filter @repo/web dev
pnpm --filter @repo/ui build

# Run in a package and all its dependencies
pnpm --filter @repo/web... build

# Run in all packages that depend on @repo/ui
pnpm --filter ...@repo/ui test

# Run in packages changed since main branch
pnpm --filter '[origin/main]' build

# Run in all apps (globbing)
pnpm --filter './apps/*' build

Adding Dependencies

# Add to a specific workspace package
pnpm --filter @repo/web add react-hook-form

# Add to root (usually devDependencies shared tools)
pnpm add -w -D typescript

# Add a workspace package as dependency
pnpm --filter @repo/web add @repo/ui --workspace

Catalog for Consistent Versions

pnpm 9+ supports a version catalog — a single source of truth for dependency versions across all packages:

# pnpm-workspace.yaml
packages:
  - 'apps/*'
  - 'packages/*'
catalog:
  react: ^19.0.0
  react-dom: ^19.0.0
  typescript: ^5.4.2
  next: ^15.0.0
// packages/*/package.json — reference catalog versions
{
  "dependencies": {
    "react": "catalog:",
    "next": "catalog:"
  }
}

Handling Peer Dependencies

In monorepos, peer dependencies need special attention. Shared packages like @repo/ui should list React as a peer dependency, not a regular dependency — apps provide their own React:

// packages/ui/package.json
{
  "peerDependencies": {
    "react": "^18 || ^19"
  },
  "peerDependenciesMeta": {
    "react": { "optional": false }
  }
}

Key Performance Tips

  • Use .npmrc with shamefully-hoist=false (default) to catch missing deps early
  • Run pnpm store prune periodically to clean unreferenced packages
  • CI: cache the pnpm store by hashing pnpm-lock.yaml
  • Use pnpm dedupe to minimize duplicate versions across the lockfile

Không spam, hủy đăng ký bất kỳ lúc nào.

Bài viết liên quan