monorepo-management

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Monorepo 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
undefined
bash
undefined

Bootstrap 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
undefined
lerna run build --scope="@myorg/core" --include-dependents
undefined

8. Turborepo Commands

8. Turborepo 命令

bash
undefined
bash
undefined

Build 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
undefined
turbo run build --profile=profile.json
undefined

9. CI/CD for Monorepo

9. Monorepo 的 CI/CD 配置

yaml
undefined
yaml
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 }}'
undefined
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 }}'
undefined

10. Version Management Across Packages

10. 跨包版本管理

bash
#!/bin/bash
bash
#!/bin/bash

sync-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"
undefined
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 "✅ 所有包已同步至版本 $MONOREPO_VERSION"
undefined

Best 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
undefined
bash
undefined

workspace:* - 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

Resources

参考资源