monorepo-management
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseMonorepo Management
Monorepo 管理
Overview
概述
Establish scalable monorepo structures that support multiple interdependent packages while maintaining build efficiency, dependency management, and deployment coordination.
构建可扩展的Monorepo结构,支持多个相互依赖的包,同时保持构建效率、依赖管理和部署协调能力。
When to Use
适用场景
- Multi-package projects
- Shared libraries across services
- Microservices architecture
- Plugin-based systems
- Multi-app platforms (web + mobile)
- Workspace dependency management
- Scaled team development
- 多包项目
- 跨服务共享库
- 微服务架构
- 基于插件的系统
- 多应用平台(Web + 移动端)
- 工作区依赖管理
- 规模化团队开发
Implementation Examples
实现示例
1. Npm Workspaces Configuration
1. Npm 工作区配置
json
{
"name": "monorepo-root",
"version": "1.0.0",
"private": true,
"workspaces": [
"packages/*",
"apps/*"
],
"devDependencies": {
"lerna": "^7.0.0",
"turbo": "^1.10.0"
},
"scripts": {
"lint": "npm run lint -r",
"test": "npm run test -r",
"build": "npm run build -r",
"clean": "npm run clean -r"
}
}json
{
"name": "monorepo-root",
"version": "1.0.0",
"private": true,
"workspaces": [
"packages/*",
"apps/*"
],
"devDependencies": {
"lerna": "^7.0.0",
"turbo": "^1.10.0"
},
"scripts": {
"lint": "npm run lint -r",
"test": "npm run test -r",
"build": "npm run build -r",
"clean": "npm run clean -r"
}
}2. Lerna Configuration
2. Lerna 配置
json
{
"name": "monorepo-with-lerna",
"version": "1.0.0",
"private": true,
"packages": [
"packages/*",
"apps/*"
],
"command": {
"bootstrap": {
"hoist": true,
"ignore": "@myorg/infra"
},
"publish": {
"conventionalCommits": true,
"createRelease": "github",
"message": "chore(release): publish"
}
}
}json
{
"name": "monorepo-with-lerna",
"version": "1.0.0",
"private": true,
"packages": [
"packages/*",
"apps/*"
],
"command": {
"bootstrap": {
"hoist": true,
"ignore": "@myorg/infra"
},
"publish": {
"conventionalCommits": true,
"createRelease": "github",
"message": "chore(release): publish"
}
}
}3. Turborepo Configuration
3. Turborepo 配置
json
{
"turbo": {
"globalDependencies": ["tsconfig.json"],
"pipeline": {
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**", ".next/**"],
"cache": true
},
"test": {
"dependsOn": ["^build"],
"cache": true,
"outputs": ["coverage/**"]
},
"lint": {
"outputs": []
},
"dev": {
"cache": false,
"persistent": true
}
}
}
}json
{
"turbo": {
"globalDependencies": ["tsconfig.json"],
"pipeline": {
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**", ".next/**"],
"cache": true
},
"test": {
"dependsOn": ["^build"],
"cache": true,
"outputs": ["coverage/**"]
},
"lint": {
"outputs": []
},
"dev": {
"cache": false,
"persistent": true
}
}
}
}4. Nx Workspace Configuration
4. Nx 工作区配置
json
{
"version": 2,
"projectNameAndRootFormat": "as-provided",
"plugins": [
"@nx/next/plugin",
"@nx/react/plugin",
"@nx/node/plugin"
],
"targetDefaults": {
"build": {
"cache": true,
"inputs": [
"production",
"^production"
]
},
"test": {
"cache": true,
"inputs": [
"default",
"^production"
]
}
}
}json
{
"version": 2,
"projectNameAndRootFormat": "as-provided",
"plugins": [
"@nx/next/plugin",
"@nx/react/plugin",
"@nx/node/plugin"
],
"targetDefaults": {
"build": {
"cache": true,
"inputs": [
"production",
"^production"
]
},
"test": {
"cache": true,
"inputs": [
"default",
"^production"
]
}
}
}5. Monorepo Directory Structure
5. Monorepo 目录结构
bash
monorepo/
├── packages/
│ ├── core/
│ │ ├── src/
│ │ ├── package.json
│ │ └── tsconfig.json
│ ├── utils/
│ │ ├── src/
│ │ ├── package.json
│ │ └── tsconfig.json
│ └── shared/
│ ├── src/
│ ├── package.json
│ └── tsconfig.json
├── apps/
│ ├── web/
│ │ ├── pages/
│ │ ├── package.json
│ │ └── next.config.js
│ ├── api/
│ │ ├── src/
│ │ ├── package.json
│ │ └── tsconfig.json
│ └── mobile/
│ ├── src/
│ ├── package.json
│ └── app.json
├── tools/
│ ├── scripts/
│ └── generators/
├── lerna.json
├── turbo.json
├── nx.json
├── package.json
├── tsconfig.json
└── .github/workflows/bash
monorepo/
├── packages/
│ ├── core/
│ │ ├── src/
│ │ ├── package.json
│ │ └── tsconfig.json
│ ├── utils/
│ │ ├── src/
│ │ ├── package.json
│ │ └── tsconfig.json
│ └── shared/
│ ├── src/
│ ├── package.json
│ └── tsconfig.json
├── apps/
│ ├── web/
│ │ ├── pages/
│ │ ├── package.json
│ │ └── next.config.js
│ ├── api/
│ │ ├── src/
│ │ ├── package.json
│ │ └── tsconfig.json
│ └── mobile/
│ ├── src/
│ ├── package.json
│ └── app.json
├── tools/
│ ├── scripts/
│ └── generators/
├── lerna.json
├── turbo.json
├── nx.json
├── package.json
├── tsconfig.json
└── .github/workflows/6. Workspace Dependencies
6. 工作区依赖
json
{
"name": "@myorg/web-app",
"version": "1.0.0",
"dependencies": {
"@myorg/core": "workspace:*",
"@myorg/shared-ui": "workspace:^",
"@myorg/utils": "workspace:~"
},
"devDependencies": {
"@myorg/test-utils": "workspace:*"
}
}json
{
"name": "@myorg/web-app",
"version": "1.0.0",
"dependencies": {
"@myorg/core": "workspace:*",
"@myorg/shared-ui": "workspace:^",
"@myorg/utils": "workspace:~"
},
"devDependencies": {
"@myorg/test-utils": "workspace:*"
}
}7. Lerna Commands
7. Lerna 命令
bash
undefinedbash
undefinedBootstrap packages and install dependencies
引导包并安装依赖
lerna bootstrap
lerna bootstrap
Install dependencies and hoist common ones
安装依赖并提升公共依赖
lerna bootstrap --hoist
lerna bootstrap --hoist
Create a new version
创建新版本
lerna version --conventional-commits
lerna version --conventional-commits
Publish all changed packages
发布所有已变更的包
lerna publish from-git
lerna publish from-git
Run command across all packages
在所有包中执行命令
lerna exec -- npm run build
lerna exec -- npm run build
Run command in parallel
并行执行命令
lerna exec --parallel -- npm run test
lerna exec --parallel -- npm run test
List all packages
列出所有包
lerna list
lerna list
Show graph of dependencies
显示依赖关系图
lerna graph
lerna graph
Run script across specific packages
在指定包中执行脚本
lerna run build --scope="@myorg/core" --include-dependents
undefinedlerna run build --scope="@myorg/core" --include-dependents
undefined8. Turborepo Commands
8. Turborepo 命令
bash
undefinedbash
undefinedBuild all packages with dependency order
按依赖顺序构建所有包
turbo run build
turbo run build
Build with specific filters
使用特定过滤器构建
turbo run build --filter=web --filter=api
turbo run build --filter=web --filter=api
Build excluding certain packages
排除特定包进行构建
turbo run build --filter='!./apps/mobile'
turbo run build --filter='!./apps/mobile'
Run tests with caching
带缓存执行测试
turbo run test --cache-dir=.turbo
turbo run test --cache-dir=.turbo
Run in development mode (no cache)
以开发模式运行(无缓存)
turbo run dev --parallel
turbo run dev --parallel
Show execution graph
显示执行图
turbo run build --graph
turbo run build --graph
Profile build times
分析构建时长
turbo run build --profile=profile.json
undefinedturbo run build --profile=profile.json
undefined9. CI/CD for Monorepo
9. Monorepo 的 CI/CD 配置
yaml
undefinedyaml
undefined.github/workflows/monorepo-ci.yml
.github/workflows/monorepo-ci.yml
name: Monorepo CI
on: [push, pull_request]
jobs:
affected:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Get changed packages
id: changed
run: |
npx lerna changed --json > changed.json
echo "packages=$(cat changed.json | jq -r '.[].name')" >> $GITHUB_OUTPUT
- name: Build changed
run: npx turbo run build --filter='${{ steps.changed.outputs.packages }}'
- name: Test changed
run: npx turbo run test --filter='${{ steps.changed.outputs.packages }}'
- name: Lint changed
run: npx turbo run lint --filter='${{ steps.changed.outputs.packages }}'undefinedname: Monorepo CI
on: [push, pull_request]
jobs:
affected:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Get changed packages
id: changed
run: |
npx lerna changed --json > changed.json
echo "packages=$(cat changed.json | jq -r '.[].name')" >> $GITHUB_OUTPUT
- name: Build changed
run: npx turbo run build --filter='${{ steps.changed.outputs.packages }}'
- name: Test changed
run: npx turbo run test --filter='${{ steps.changed.outputs.packages }}'
- name: Lint changed
run: npx turbo run lint --filter='${{ steps.changed.outputs.packages }}'undefined10. Version Management Across Packages
10. 跨包版本管理
bash
#!/bin/bashbash
#!/bin/bashsync-versions.sh
sync-versions.sh
Use lerna to keep versions in sync
使用Lerna保持版本同步
lerna version --exact --force-publish
lerna version --exact --force-publish
Or manually sync package.json versions
或手动同步package.json版本
MONOREPO_VERSION=$(jq -r '.version' package.json)
for package in packages/*/package.json; do
jq --arg version "$MONOREPO_VERSION" '.version = $version' "$package" > "$package.tmp"
mv "$package.tmp" "$package"
done
echo "✅ All packages synced to version $MONOREPO_VERSION"
undefinedMONOREPO_VERSION=$(jq -r '.version' package.json)
for package in packages/*/package.json; do
jq --arg version "$MONOREPO_VERSION" '.version = $version' "$package" > "$package.tmp"
mv "$package.tmp" "$package"
done
echo "✅ 所有包已同步至版本 $MONOREPO_VERSION"
undefinedBest Practices
最佳实践
✅ DO
✅ 建议
- Use workspace protocols for dependencies
- Implement shared tsconfig for consistency
- Cache build outputs in CI/CD
- Filter packages in CI to avoid unnecessary builds
- Hoist common dependencies
- Document workspace structure
- Use consistent versioning strategy
- Implement pre-commit hooks across workspace
- Test cross-package dependencies
- Version packages independently when appropriate
- 使用工作区协议管理依赖
- 实现共享tsconfig以保持一致性
- 在CI/CD中缓存构建输出
- 在CI中过滤包以避免不必要的构建
- 提升公共依赖
- 文档化工作区结构
- 使用一致的版本控制策略
- 在工作区中实现提交前钩子
- 测试跨包依赖
- 在合适时独立版本化包
❌ DON'T
❌ 不建议
- Create circular dependencies
- Use hardcoded versions for workspace packages
- Build all packages when only one changed
- Forget to update lock files
- Ignore workspace boundaries
- Create tightly coupled packages
- Skip dependency management
- Use different tooling per package
- 创建循环依赖
- 为工作区包使用硬编码版本
- 仅单个包变更时构建所有包
- 忘记更新锁文件
- 忽略工作区边界
- 创建紧耦合的包
- 跳过依赖管理
- 为不同包使用不同工具链
Workspace Dependency Resolution
工作区依赖解析规则
bash
undefinedbash
undefinedworkspace:* - Use exact version in workspace
workspace:* - 使用工作区中的精确版本
"@myorg/core": "workspace:*"
"@myorg/core": "workspace:*"
workspace:^ - Use compatible version
workspace:^ - 使用兼容版本
"@myorg/shared": "workspace:^"
"@myorg/shared": "workspace:^"
workspace:~ - Use patch-compatible version
workspace:~ - 使用补丁兼容版本
"@myorg/utils": "workspace:~"
undefined"@myorg/utils": "workspace:~"
undefined