跪拜 Guibai
← All articles
Frontend

Monorepo vs Multi-Repo: The Front-End Repository Management Playbook

By 前端嘿起 ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

Repository architecture directly shapes build times, CI costs, and how fast a team can ship. Choosing the wrong model — or the right model without the supporting tooling — leads to version conflicts, hour-long pipelines, and onboarding friction that compounds as the codebase grows.

Summary

Front-end teams scaling beyond a single repository hit predictable pain points: bloated clone times, dependency version drift, redundant builds, and tangled release coordination. Two architectural patterns dominate the response — Monorepo and Multi-repo — each with distinct trade-offs in code sharing, build efficiency, and team autonomy. Monorepo keeps all packages in one repository with workspace-level dependency resolution and incremental builds, while Multi-repo isolates each module in its own repository for independent versioning and access control.

The tooling landscape has matured around four main options. pnpm Workspaces provide lightweight, disk-efficient package linking. Turborepo layers high-speed caching and parallel task orchestration on top. NX delivers a full-featured build system with code generation and dependency graphing. Lerna remains a focused choice for versioning and publishing workflows. Many teams combine these — pnpm plus Turborepo is a common stack — and the article walks through a complete project setup with shared TypeScript configs, cross-package aliases, and CI/CD orchestration.

Beyond tool choice, the operational practices matter just as much. Unified dependency versions, strict avoidance of circular dependencies, remote build caching, shared ESLint/Prettier configs, and automated changelog generation with Changesets all prevent the chaos that multi-repo setups can breed. A hybrid model — grouping tightly coupled packages in a Monorepo while keeping independent services in separate repos — often fits real-world team structures better than a pure approach.

Takeaways
Single repositories become painful when clone times, IDE load, and Git operations slow down under codebase weight.
Multi-repo setups cause dependency version drift across packages, making upgrades and debugging inconsistent.
Monorepo keeps all packages in one repo with workspace linking, enabling direct cross-package imports without publishing to npm.
Multi-repo isolates each module in its own repository, giving teams independent release cycles and fine-grained access control.
pnpm Workspaces offer fast, disk-efficient package management with simple YAML-based workspace configuration.
Turborepo adds incremental builds and remote caching, rebuilding only packages affected by a change.
NX provides a full toolchain with code generators, dependency graph visualization, and affected-project detection.
Lerna focuses on version bumping and publishing, supporting both independent and fixed versioning modes.
Git Submodule and Git Subtree are native Git options for Multi-repo, but add operational complexity around updates and merges.
Rush targets large-scale dependency management with version policies and a unified install-build-publish workflow.
Changesets automates semantic versioning and CHANGELOG generation across multiple packages.
Cross-repo CI/CD can be orchestrated with GitHub Actions artifacts or Jenkins Pipeline stash/unstash steps.
A hybrid model — Monorepo for tightly coupled front-end packages, separate repos for independent services — often fits best.
Circular dependencies break builds; extracting shared types or using event buses decouples packages safely.
Build cache invalidation is usually caused by misconfigured output directories or missing global dependency declarations.
Dependency version conflicts are resolved with pnpm overrides, workspace protocols, or root-level resolutions.
Shared tsconfig, ESLint, and Prettier configs prevent drift in code style and compiler settings across packages.
Clear directory separation into apps/ and packages/ layers keeps runnable applications distinct from shareable libraries.
Automated dependency updates via Renovate or Dependabot reduce the manual toil of keeping versions aligned.
Onboarding speed improves with Dockerized dev environments, architecture docs, and step-by-step setup guides.
Conclusions

Most teams don't need a pure Monorepo or pure Multi-repo; a hybrid approach that groups tightly coupled packages together while isolating independent services avoids the worst downsides of both extremes.

The real cost of Multi-repo isn't the repository count — it's the coordination tax of version alignment, cross-repo PRs, and duplicated CI pipelines that grow linearly with each new repository.

Turborepo's remote caching is an underused lever: sharing build artifacts across CI runs and developer machines can cut pipeline times by 50-80% without changing any application code.

pnpm's strict dependency resolution — where packages can't access undeclared dependencies — prevents the phantom dependency bugs that routinely break Multi-repo setups when hoisting behavior differs between environments.

Version management tools like Changesets matter more as team size grows; without automated changelogs and version bumping, release notes become fiction and breaking changes slip through unreported.

Git Submodule and Subtree are often chosen for their zero-dependency appeal, but their operational friction — forgotten updates, detached HEAD states, merge conflicts on submodule pointers — makes them a liability beyond two or three repos.

The choice between NX and Turborepo is less about features and more about philosophy: NX provides an opinionated, batteries-included framework, while Turborepo layers composably on top of your existing package manager and task runner.

Circular dependencies are a design smell that tooling can detect but not fix; the only durable solution is extracting shared contracts into a separate package that both sides depend on.

CI/CD for Multi-repo is fundamentally a graph problem — build artifacts need to flow between repositories — and most teams solve it with ad-hoc artifact uploads rather than a proper package registry, which creates reproducibility gaps.

Standardizing on a single TypeScript version and compiler options across all packages eliminates an entire class of build errors that manifest only when packages are composed together at runtime.

Concepts & terms
Monorepo
A single Git repository containing multiple projects or packages, enabling direct code sharing and unified dependency management through workspace features.
Multi-repo
An architecture where each project or module lives in its own independent Git repository, providing isolation for versioning, access control, and release cycles.
pnpm Workspace
A pnpm feature that links multiple packages within a single repository, allowing cross-package imports without publishing to npm and enforcing strict dependency boundaries.
Turborepo
A build orchestration tool by Vercel that caches task outputs and rebuilds only packages affected by code changes, dramatically speeding up CI and local development.
NX
A build system and Monorepo management tool with code generators, dependency graph visualization, and affected-project detection, offering an opinionated full toolchain.
Lerna
A tool focused on version bumping and npm publishing across multiple packages in a Monorepo, supporting both independent and fixed versioning strategies.
Git Submodule
A native Git mechanism that embeds one repository as a subdirectory inside another, maintaining a pointer to a specific commit of the child repository.
Git Subtree
A Git strategy that merges the full history of a sub-repository into a subdirectory of the main repository, making the code directly part of the parent repo.
Changesets
A tool that tracks intended version bumps and generates CHANGELOG entries, then applies them across packages in a coordinated release step.
Rush
A Microsoft-built Monorepo manager that enforces version policies, handles installation and linking, and provides a unified publish workflow for large-scale projects.
Incremental Build
A build strategy that recompiles only the code that changed and its dependents, skipping unchanged packages to reduce build times.
Remote Cache
A shared cache, often cloud-hosted, that stores build outputs so that team members and CI runners can reuse previously computed results instead of rebuilding.
Circular Dependency
A situation where Package A depends on Package B and Package B depends on Package A, causing build failures and runtime resolution errors.
Workspace Protocol
A pnpm feature (workspace:^) that links packages locally during development while resolving to the correct version range when published to a registry.
Source: juejin.cn ↗ Google Translate ↗ Backup ↗