
pnpm Workspaces Explained: Scale Multi-Package Repos Without the npm Headaches
pnpm workspaces are faster and leaner than npm or yarn equivalents, but the setup trips people up. This hands-on guide covers workspace linking, shared deps, version control strategies, and publishing flows so your monorepo just works.
Every frontend team eventually outgrows a single package.json. You start extracting shared utilities, then a component library, then a config package — and suddenly you're managing dependencies across five packages with npm or yarn, watching your node_modules consume 3GB of disk space. pnpm workspaces solve this elegantly with a content-addressable store and strict dependency isolation.
Why pnpm Over npm or Yarn Workspaces?
The core advantage is pnpm's storage model. Instead of duplicating packages across workspaces, pnpm uses hard links to a global content-addressable store. If five packages depend on React 19, there's one copy on disk, not five. On a large monorepo, this typically saves 50-70% disk space and makes installs significantly faster.
But the real win is strictness. pnpm creates a non-flat node_modules structure by default, which means packages can only access dependencies they explicitly declare. No more phantom dependencies — if it's not in your package.json, you can't import it.
Setting Up Your Workspace
Create a pnpm-workspace.yaml at the root of your project:
# pnpm-workspace.yaml
packages:
- "apps/*"
- "packages/*"
- "tools/*"
Then structure your monorepo with clear boundaries between apps and shared packages. Each directory listed in the workspace config gets its own package.json and can declare dependencies on other workspace packages using the workspace: protocol.
// apps/web/package.json
{
"name": "@myorg/web",
"dependencies": {
"@myorg/ui": "workspace:*",
"@myorg/utils": "workspace:^1.0.0",
"next": "^16.0.0",
"react": "^19.0.0"
}
}
The workspace:* protocol tells pnpm to always resolve to the local version. When you publish, pnpm automatically replaces it with the actual version number. The workspace:^ variant respects semver ranges, which is useful for packages you might eventually publish to npm.
Running Scripts Across Packages
pnpm's --filter flag is your primary tool for targeting specific packages. You can filter by name, by directory, or by what changed in git. Combined with the -r (recursive) flag, you can orchestrate builds across your entire workspace with surgical precision.
For CI pipelines, the git-based filter is particularly powerful. Running pnpm --filter "...[origin/main]" build builds only packages that changed since the main branch — and their dependents. This keeps CI fast as your monorepo grows.
Common Pitfalls
The most frequent issue teams hit is the peer dependency strictness. pnpm enforces peer dependencies by default, which surfaces real problems but can be noisy during migration. Set auto-install-peers=true in your .npmrc for a smoother transition, then tighten it later.
Another gotcha: hoisting. Some tools (notably React Native and certain bundlers) expect a flat node_modules. pnpm lets you selectively hoist packages via public-hoist-pattern in .npmrc, but the default strict behavior is what you want for most web projects.
pnpm + Turborepo: The Winning Combination
pnpm handles package management and dependency resolution. Turborepo handles task orchestration and caching. Together, they form the most popular monorepo stack in the frontend ecosystem. pnpm ensures correct, efficient dependency graphs while Turborepo ensures you never rebuild what hasn't changed.
Start with pnpm workspaces for your next multi-package project. The strict dependency model catches real bugs, the disk savings are substantial, and the migration from npm or yarn is straightforward. Your future self — and your CI bill — will thank you.
Get weekly highlights
No spam, unsubscribe anytime.
Dub.co
Short links & analytics for developers — track clicks, create branded links, manage affiliate URLs with ease.
Ranked.ai
AI-powered SEO & PPC service — fully managed, white hat, and built for modern search engines. Starting at $99/month.



Comments (0)
Sign in to comment
No comments yet. Be the first to comment!