把构建缓存拆成三层之后,CI 到底快在哪
流水线从 14 分钟掉到 6 分钟,靠的不是换更贵的机器,而是把缓存按失效范围拆开,让最容易命中的那层先命中。
本文目录
缓存的收益不取决于你存了多少东西,而取决于失效范围有多大。把依赖、编译中间结果和最终产物混在一个目录里,任何一次源码改动都会让整个缓存作废。
01三层各自解决什么
| 层 | 键 | 失效条件 | 命中后省下的时间 |
|---|---|---|---|
| 依赖 | 锁文件哈希 | 依赖版本变化 | 约 3 分钟 |
| 编译 | 源码哈希 + 工具链版本 | 源码或工具链变化 | 约 4 分钟 |
| 产物 | 完整构建输入哈希 | 任一输入变化 | 整段跳过构建 |
yaml
cache:
- key: deps-${{ hashFiles('pnpm-lock.yaml') }}
paths: [node_modules]
- key: build-${{ hashFiles('src/**', 'tsconfig.json') }}
paths: [.cache/build]拆分之后最明显的变化不是平均耗时,而是方差:以前 8 到 20 分钟浮动,现在稳定在 5 到 7 分钟,排队和超时也一起减少了。