218 lines
5.0 KiB
Markdown
218 lines
5.0 KiB
Markdown
---
|
|
name: monorepo-management
|
|
description: Master monorepo management with Turborepo, Nx, and pnpm workspaces to build efficient, scalable multi-package repositories with optimized builds and dependency management. Use when setting up monorepos, optimizing builds, or managing shared dependencies.
|
|
---
|
|
|
|
# Monorepo Management
|
|
|
|
Build efficient, scalable monorepos that enable code sharing, consistent tooling, and atomic changes across multiple packages and applications.
|
|
|
|
## When to Use This Skill
|
|
|
|
- Setting up new monorepo projects
|
|
- Migrating from multi-repo to monorepo
|
|
- Optimizing build and test performance
|
|
- Managing shared dependencies
|
|
- Implementing code sharing strategies
|
|
- Setting up CI/CD for monorepos
|
|
- Versioning and publishing packages
|
|
- Debugging monorepo-specific issues
|
|
|
|
## Core Concepts
|
|
|
|
### 1. Why Monorepos?
|
|
|
|
**Advantages:**
|
|
|
|
- Shared code and dependencies
|
|
- Atomic commits across projects
|
|
- Consistent tooling and standards
|
|
- Easier refactoring
|
|
- Simplified dependency management
|
|
- Better code visibility
|
|
|
|
**Challenges:**
|
|
|
|
- Build performance at scale
|
|
- CI/CD complexity
|
|
- Access control
|
|
- Large Git repository
|
|
|
|
### 2. Monorepo Tools
|
|
|
|
**Package Managers:**
|
|
|
|
- pnpm workspaces (recommended)
|
|
- npm workspaces
|
|
- Yarn workspaces
|
|
|
|
**Build Systems:**
|
|
|
|
- Turborepo (recommended for most)
|
|
- Nx (feature-rich, complex)
|
|
- Lerna (older, maintenance mode)
|
|
|
|
## Turborepo Setup
|
|
|
|
### Initial Setup
|
|
|
|
```bash
|
|
# Create new monorepo
|
|
npx create-turbo@latest my-monorepo
|
|
cd my-monorepo
|
|
|
|
# Structure:
|
|
# apps/
|
|
# web/ - Next.js app
|
|
# docs/ - Documentation site
|
|
# packages/
|
|
# ui/ - Shared UI components
|
|
# config/ - Shared configurations
|
|
# tsconfig/ - Shared TypeScript configs
|
|
# turbo.json - Turborepo configuration
|
|
# package.json - Root package.json
|
|
```
|
|
|
|
### Configuration
|
|
|
|
```json
|
|
// turbo.json
|
|
{
|
|
"$schema": "https://turbo.build/schema.json",
|
|
"globalDependencies": ["**/.env.*local"],
|
|
"pipeline": {
|
|
"build": {
|
|
"dependsOn": ["^build"],
|
|
"outputs": ["dist/**", ".next/**", "!.next/cache/**"]
|
|
},
|
|
"test": {
|
|
"dependsOn": ["build"],
|
|
"outputs": ["coverage/**"]
|
|
},
|
|
"lint": {
|
|
"outputs": []
|
|
},
|
|
"dev": {
|
|
"cache": false,
|
|
"persistent": true
|
|
},
|
|
"type-check": {
|
|
"dependsOn": ["^build"],
|
|
"outputs": []
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
```json
|
|
// package.json (root)
|
|
{
|
|
"name": "my-monorepo",
|
|
"private": true,
|
|
"workspaces": ["apps/*", "packages/*"],
|
|
"scripts": {
|
|
"build": "turbo run build",
|
|
"dev": "turbo run dev",
|
|
"test": "turbo run test",
|
|
"lint": "turbo run lint",
|
|
"format": "prettier --write \"**/*.{ts,tsx,md}\"",
|
|
"clean": "turbo run clean && rm -rf node_modules"
|
|
},
|
|
"devDependencies": {
|
|
"turbo": "^1.10.0",
|
|
"prettier": "^3.0.0",
|
|
"typescript": "^5.0.0"
|
|
},
|
|
"packageManager": "pnpm@8.0.0"
|
|
}
|
|
```
|
|
|
|
### Package Structure
|
|
|
|
```json
|
|
// packages/ui/package.json
|
|
{
|
|
"name": "@repo/ui",
|
|
"version": "0.0.0",
|
|
"private": true,
|
|
"main": "./dist/index.js",
|
|
"types": "./dist/index.d.ts",
|
|
"exports": {
|
|
".": {
|
|
"import": "./dist/index.js",
|
|
"types": "./dist/index.d.ts"
|
|
},
|
|
"./button": {
|
|
"import": "./dist/button.js",
|
|
"types": "./dist/button.d.ts"
|
|
}
|
|
},
|
|
"scripts": {
|
|
"build": "tsup src/index.ts --format esm,cjs --dts",
|
|
"dev": "tsup src/index.ts --format esm,cjs --dts --watch",
|
|
"lint": "eslint src/",
|
|
"type-check": "tsc --noEmit"
|
|
},
|
|
"devDependencies": {
|
|
"@repo/tsconfig": "workspace:*",
|
|
"tsup": "^7.0.0",
|
|
"typescript": "^5.0.0"
|
|
},
|
|
"dependencies": {
|
|
"react": "^18.2.0"
|
|
}
|
|
}
|
|
```
|
|
|
|
## Detailed patterns and worked examples
|
|
|
|
Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.
|
|
|
|
## Best Practices
|
|
|
|
1. **Consistent Versioning**: Lock dependency versions across workspace
|
|
2. **Shared Configs**: Centralize ESLint, TypeScript, Prettier configs
|
|
3. **Dependency Graph**: Keep it acyclic, avoid circular dependencies
|
|
4. **Cache Effectively**: Configure inputs/outputs correctly
|
|
5. **Type Safety**: Share types between frontend/backend
|
|
6. **Testing Strategy**: Unit tests in packages, E2E in apps
|
|
7. **Documentation**: README in each package
|
|
8. **Release Strategy**: Use changesets for versioning
|
|
|
|
## Common Pitfalls
|
|
|
|
- **Circular Dependencies**: A depends on B, B depends on A
|
|
- **Phantom Dependencies**: Using deps not in package.json
|
|
- **Incorrect Cache Inputs**: Missing files in Turborepo inputs
|
|
- **Over-Sharing**: Sharing code that should be separate
|
|
- **Under-Sharing**: Duplicating code across packages
|
|
- **Large Monorepos**: Without proper tooling, builds slow down
|
|
|
|
## Publishing Packages
|
|
|
|
```bash
|
|
# Using Changesets
|
|
pnpm add -Dw @changesets/cli
|
|
pnpm changeset init
|
|
|
|
# Create changeset
|
|
pnpm changeset
|
|
|
|
# Version packages
|
|
pnpm changeset version
|
|
|
|
# Publish
|
|
pnpm changeset publish
|
|
```
|
|
|
|
```yaml
|
|
# .github/workflows/release.yml
|
|
- name: Create Release Pull Request or Publish
|
|
uses: changesets/action@v1
|
|
with:
|
|
publish: pnpm release
|
|
env:
|
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
```
|