Why Your Monorepo Is Slowing Down and How pnpm & Rush Can Fix It
This article examines the scalability and reliability problems of a Yarn‑workspace based monorepo—such as command inconsistency, slow publishing, phantom dependencies, duplicate packages, and lockfile conflicts—and presents pnpm and Rush as comprehensive solutions with practical guidelines for package referencing and workspace protocols.
Introduction
The team manages all business projects with a monorepo using Yarn workspaces and Lerna, but as the number of projects grows, stability and developer experience suffer, revealing that the current architecture can no longer support the expanding codebase.
Existing Problems
Inconsistent Commands
Three commands (yarn, yarn workspace, lerna) overlap, confusing newcomers.
Slow Publish Speed
Publishing an app installs all dependencies of every app and package, and builds all packages instead of only those required by the target app.
Phantom Dependencies
A library that uses a package not listed in its dependencies creates a phantom (implicit) dependency, which is amplified in the current monorepo architecture.
Version uncertainty of phantom dependencies can cause runtime bugs because the actual version of a transitive dependency is determined by the consuming app’s developer.
NPM Doppelganger
Identical packages may be installed multiple times, leading to duplicate bundles and potential singleton conflicts.
Yarn Duplicate
Yarn duplicate and its solutions are discussed.
Yarn v1 may install a different version of a package than npm, causing duplication.
peerDependencies Risks
Dependency hoisting can introduce bugs when peerDependencies are not satisfied.
app1 depends on [email protected]
app2 depends on [email protected]
[email protected] lists [email protected] as a peerDependency, so app2 should install [email protected].
--apps<br/> --app1<br/> --app2<br/>--node_modules<br/> [email protected]<br/> [email protected]<br/>Without the correct version, [email protected] may incorrectly reference [email protected].
Missing Package Reference Standards
Three current reference methods:
Source reference via package name (requires host project build configuration).
Source reference via file path (directly includes source files, risky under hoisting).
Product reference (uses built artifact).
Uncertain Package Version References
When a package is published to npm, how should an app specify its version? The article shows examples with * and explicit versions, and explains Yarn’s resolution steps.
{
"name": "package1",
"version": "1.0.0"
} {
"name": "app1",
"dependencies": {
"package-1": "?" // should this be * or 1.0.0?
}
}Yarn first checks for a matching local version, links it if found, otherwise pulls from the remote registry.
Note: * cannot match prerelease versions (see issue #6719).
yarn.lock Conflicts
pnpm automates lockfile conflict resolution, while Yarn requires manual handling, often leading to Git binary conflicts.
Solution
pnpm
Fast, disk‑space‑efficient package manager.
pnpm stores packages in a non‑flattened node_modules structure with symlinks, avoiding deep nesting and duplicate copies.
node_modules<br/>└─ foo<br/> ├─ index.js<br/> └─ package.json<br/>└─ bar<br/> ├─ index.js<br/> └─ package.json<br/>Benefits:
Eliminates phantom dependencies by isolating each package’s own dependencies.
Deduplicates identical versions via symlinks, reducing bundle size.
Rush
A scalable monorepo manager for the web.
Key advantages:
Unified commands (e.g., rush install, rush build -t @monorepo/app1).
Powerful dependency analysis (e.g., rush install -t @monorepo/app1 installs only needed deps).
Ensures version consistency via rush check, rush add -p, and ensureConsistentVersions.
Package Reference Guidelines
Three reference styles:
Product reference : app consumes built artifact; fast but hot‑update may be slow.
Source reference : use main field to point to source; fast hot‑updates but requires host project adaptation.
Internal features should not be published externally and should use source reference; external packages must have a build step.
Rush build supports caching; with fine‑grained apps and reusable packages, incremental builds are possible.
Workspace Protocol
Before pnpm and Yarn workspaces, Rush linked all packages into a common folder, effectively providing the same workspace behavior.
Enabling PNPM workspace allows using workspace: ranges (e.g., workspace:*) to guarantee local version resolution.
{
"dependencies": {
"foo": "workspace:*",
"bar": "workspace:~",
"qar": "workspace:^",
"zoo": "workspace:^1.5.0"
}
}Problem Records
Monorepo Project Dependencies Duplicate
Similar to Yarn duplicate but occurs in any monorepo. Different apps may install different versions of the same library, leading to multiple copies in the final bundle.
{
"name": "fake-project",
"version": "1.0.0",
"dependencies": {
"@fake-project/app1": "1.0.0",
"@fake-project/package1": "1.0.0"
}
}Solution: use Rush preferredVersions to force a single version, or Yarn‑specific tools like yarn-deduplicate or resolutions.
prettier & eslint
Each project installs its own prettier and eslint as devDependencies, avoiding global installations. Configuration files ( .prettierrc.js, .eslintrc.js) are placed in each package.
git hooks
Use husky ‑like hooks via Rush autoinstallers. Example scripts for commit-msg and pre-commit invoke Rush commands that run commitlint and eslint respectively.
#!/bin/sh
node common/scripts/install-run-rush.js commitlint || exit $? #!/bin/sh
node common/scripts/install-run-rush.js lint || exit $?Appendix
Common Commands
Key Yarn vs. Rush command mapping (install, upgrade, add, build, etc.) is provided for quick reference.
Workflow
# Pull latest changes
$ git pull
# Update NPM dependencies
$ rush update
# Rebuild dependencies of @monorepo/app1 (excluding the app itself)
$ rush rebuild -T @monorepo/app1
# Enter the app directory and start it
$ cd ./apps/app1
$ rushx start # or rushx devReferences
Links to official documentation for Yarn, pnpm, Rush, and related issues are listed.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
