Monorepos consolidate multiple packages in a single repository. This guide covers tooling, workflows, and patterns for effective monorepo management.
Why Monorepos?#
- Unified versioning: All packages at compatible versions
- Code sharing: Easy cross-package imports
- Atomic changes: Single commit across packages
- Simplified tooling: One CI/CD pipeline
Project Structure#
my-monorepo/
├── apps/
│ ├── web/ # Next.js app
│ ├── mobile/ # React Native app
│ └── docs/ # Documentation site
├── packages/
│ ├── ui/ # Shared UI components
│ ├── config/ # Shared configs
│ └── utils/ # Shared utilities
├── package.json
├── pnpm-workspace.yaml
└── turbo.json
Setting Up with pnpm#
# pnpm-workspace.yaml
packages:
- 'apps/*'
- 'packages/*'1// turbo.json
2{
3 "tasks": {
4 "build": {
5 "dependsOn": ["^build"],
6 "outputs": ["dist/**", ".next/**"]
7 },
8 "dev": {
9 "cache": false,
10 "persistent": true
11 }
12 }
13}Filtering Packages#
pnpm turbo build --filter=@company/web
pnpm turbo build --filter=@company/web...
pnpm turbo build --filter=...[origin/main]Shared Configurations#
1// packages/config/tsconfig/base.json
2{
3 "compilerOptions": {
4 "target": "ES2022",
5 "module": "ESNext",
6 "strict": true
7 }
8}Best Practices#
- Keep packages focused
- Use workspace protocol for internal deps
- Configure proper outputs for caching
- Document package APIs
Conclusion#
Monorepos require upfront investment but pay dividends in developer productivity. Start with pnpm workspaces and Turborepo.