Skip to content

ADR-002: pnpm Workspace Monorepo

Date: 2026-02-27 Authors: Jean-Francois Meyers Scope: granit-front

The Granit frontend framework is composed of multiple packages with inter-package dependencies. The package manager must:

  • Manage a multi-package workspace with local symbolic links
  • Efficiently resolve shared dependencies (hoisting)
  • Offer fast resolution and installation performance
  • Support the workspace:* protocol for internal dependencies

Use pnpm as the exclusive package manager for the monorepo.

Configuration in pnpm-workspace.yaml:

packages:
- 'packages/@granit/*'

Inter-package dependencies use workspace:* in peerDependencies:

{
"peerDependencies": {
"@granit/api-client": "workspace:*"
}
}
  • Advantage: content-addressable store, isolated node_modules, native workspace:* protocol, fast installs
  • Disadvantage: less widespread than npm, pnpm-specific lock file
  • Advantage: zero additional tooling (ships with Node.js)
  • Disadvantage: aggressive hoisting creates phantom dependencies, no workspace:* protocol, slower performance
  • Advantage: Plug’n’Play eliminates node_modules, zero-installs
  • Disadvantage: PnP complicates Vite and TypeScript tool integration, zero-installs bloat the repository
Criterionpnpmnpm workspacesYarn Berry
Dependency isolationStrict (non-flat)Hoisted (phantom deps)Strict (PnP)
Install performanceFast (content-addressable)ModerateFast (zero-install)
workspace:* protocolNativeNot supportedSupported
Vite compatibilityWorks out of the boxWorksRequires PnP configuration
Cross-package commandspnpm -r exec, --filternpm -ws execyarn workspaces foreach
Community adoptionGrowing rapidlyUniversalDeclining
  • Strict isolation: no phantom dependencies thanks to pnpm’s non-flat node_modules
  • Performance: content-addressable store shared across projects, near-instant installs after the first run
  • workspace:*: automatic resolution of local packages with version replacement at publication
  • pnpm -r exec: command execution across all packages (lint, tsc)
  • --filter: targeted execution on a specific package
  • Adoption: pnpm is less widespread than npm, which may surprise new contributors
  • Lock file: pnpm-lock.yaml is incompatible with other managers, imposing pnpm on all contributors
  • Overrides: pnpm-specific syntax in package.json (pnpm.overrides)

This decision should be re-evaluated if:

  • npm workspaces gains native workspace:* support and strict isolation
  • A new package manager emerges with compelling advantages over pnpm
  • The pnpm project is abandoned or maintenance slows significantly