pnpm Workspaces: The Developer's Guide to Efficient Monorepo Package Management
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
.npmrcwithshamefully-hoist=false(default) to catch missing deps early - Run
pnpm store pruneperiodically to clean unreferenced packages - CI: cache the pnpm store by hashing
pnpm-lock.yaml - Use
pnpm dedupeto minimize duplicate versions across the lockfile
Admin
Cal.com
Open source scheduling — tự host booking system, thay thế Calendly. Free & privacy-first.
Bình luận (0)
Đăng nhập để bình luận
Chưa có bình luận nào. Hãy là người đầu tiên!