Monorepo vs Multirepo: Concepts, Tools, and Step‑by‑Step Setup with pnpm Workspaces
This article explains the differences between Monorepo and Multirepo architectures, reviews popular Monorepo tools, and provides a detailed step‑by‑step guide to building a Vue‑based Monorepo project using pnpm Workspaces, including workspace configuration, shared package creation, and dependency management.
Monorepo (single repository) is a strategy that uses one repository to manage multiple packages, while Multirepo (multiple repositories) isolates each project in its own repository.
In a Monorepo, a common package.json lives at the root, and each sub‑package also has its own package.json . Packages can reference each other via the name field defined in their respective package.json files.
# monorepo directory structure
monorepo-demo
├── packages
│ ├─ module-a
│ │ ├─ src # source of module a
│ │ ├─ node_modules # module a dependencies
│ │ └─ package.json # module a specific deps
│ └─ module-b
│ ├─ src
│ └─ package.json
├── .eslintrc # project‑wide config
├── node_modules # shared deps
└── package.json # shared depsMultirepo keeps each project in a separate repository, each with its own package.json :
# multirepo-a directory structure
multirepo-a
├── src
├── .eslintrc
├── node_modules
└── package.json
# multirepo-b directory structure
multirepo-b
├── src
├── .eslintrc
├── node_modules
└── package.jsonPopular Monorepo tools in the front‑end ecosystem (as of 2024) include Pnpm Workspaces , Yarn Workspaces , npm Workspaces , Rush , Turborepo , Lerna , Yalc , and Nx . The article strongly recommends Pnpm Workspaces for dependency management.
Package managers such as npm, Yarn, and pnpm support workspaces, allowing shared dependencies across sub‑projects and simplifying installation and build processes.
Step‑by‑step project setup:
Globally install pnpm: npm i pnpm -g
Create a new project folder pnpm-monorepo and run pnpm init to generate a root package.json .
Create a packages directory to hold sub‑packages.
Inside packages , create a shared library libc-shared and set its package.json name to @libc/shared with main pointing to src/index.js .
Create a UI component package libc-ui (cloned from ViewUIPlus) and set its name to @libc/ui , also pointing main to src/index.js .
Generate two Vue applications vue-dom1 and vue-dom2 using pnpm create vue@latest . Move their common dependencies and devDependencies to the root package.json and run pnpm install once.
Configure the workspace by adding a pnpm-workspace.yaml at the root:
packages:
# all packages in direct subdirs of packages/
- 'packages/*'The final structure looks like:
pnpm-monorepo/
├── packages/
│ ├── libc-shared/
│ ├── libc-ui/
│ ├── vue-dome1/
│ └── vue-dome2/
├── package.json
└── pnpm-workspace.yamlSharing sub‑packages: install a shared package with the --workspace flag, e.g., pnpm install @libc/shared --workspace -w , which adds "@libc/shared": "workspace:^" to the dependent project's package.json . Then import it in Vue code: import { isObject } from '@libc/shared' .
If a component import fails (e.g., missing ./base ), add the missing extensions in vite.config.js : resolve: { extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue'] } Also import the style file in libc-ui/src/index.js : import "./styles/index.less"; Install global dependencies like lodash across the workspace with pnpm install lodash -w . If only one sub‑project needs a dependency, install it locally either by navigating to the sub‑package directory and running pnpm install lodash or by using the --filter flag, e.g., pnpm install lodash --filter vue-demo1 . Reference links: GitHub repository burc-li/pnpm-monorepo and articles on why pnpm+Monorepo is a best practice for component libraries and the 2024 Monorepo tool selection guide.
Rare Earth Juejin Tech Community
Juejin, a tech community that helps developers grow.
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.