CI/CD Monorepo 缓存:流水线慢,先别怪机器少
CI/CD Monorepo 缓存流水线慢先别怪机器少Monorepo 项目一大CI/CD 很容易变成发布瓶颈。每个 PR 都全量安装依赖、全量构建、全量测试机器再多也会被浪费。很多团队第一反应是加 runner加到最后账单上去了速度没下来。流水线慢先别怪机器少先看缓存和变更范围。Monorepo CI 的核心目标是只跑受影响的任务复用能复用的结果并且保证缓存可信。一、先算影响范围flowchart TD A[Git Diff] -- B[Package Graph] B -- C[Affected Apps] B -- D[Affected Libraries] C -- E[Build Tasks] D -- F[Test Tasks] E -- G[Cache Lookup] F -- G G -- H[Run Or Restore]没有依赖图就只能全量跑。前端 Monorepo 里一个工具函数改动可能影响多个应用一个文档改动可能不需要跑任何构建。要让流水线知道差别。二、缓存 key 要包含真正影响输出的内容缓存不是简单按分支名存一下。依赖 lockfile、构建配置、环境变量、Node 版本、源码 hash 都可能影响产物。cache_key: node_version: 20.15.0 lockfile_hash: ${{ hashFiles(pnpm-lock.yaml) }} package_hash: ${{ hashFiles(packages/ui/src/**) }} build_config_hash: ${{ hashFiles(vite.config.ts) }}key 太粗会误用旧产物key 太细会导致缓存命中率低。要按任务类型设计而不是全项目一个 key。三、依赖缓存和构建缓存分开依赖安装缓存解决的是下载慢构建缓存解决的是重复计算。两者不要混在一起。cache_layers ├── package_manager_store: pnpm/npm/yarn cache ├── node_modules: usually avoid cross-platform reuse ├── build_output: dist, .next, storybook ├── test_cache: jest/vitest transform cache └── docker_layer_cache: image build layers依赖缓存失效不应该让构建缓存全部失效。Docker layer cache 也要单独治理否则一个环境变量变化就会让镜像全层重建。四、缓存要可观测、可清理缓存命中率、恢复耗时、上传耗时、缓存大小都要看。缓存太大时恢复时间可能比重新构建还长。{ task: build:web-admin, cache_hit: true, restore_ms: 3200, saved_ms: 48000, cache_size_mb: 180 }如果一个缓存恢复 20 秒只节省 5 秒构建那就该删。缓存是优化手段不是收藏夹。五、总结Monorepo CI/CD 优化先从影响范围分析和缓存设计开始。只跑受影响任务按真实输入设计 cache key拆分依赖缓存、构建缓存和 Docker 缓存再用指标验证收益。流水线快不是靠堆机器堆出来的。缓存命中、任务裁剪和可观测性做好发布节奏才会稳定下来。