GitLab并行Jest测试缓存优化:如何高效设置缓存键?
Jest并行测试缓存键优化方案
问题背景
我们的仓库用Jest执行测试耗时长达20分钟,已在GitLab配置4个并行作业:
stage: test parallel: 4 script: - yarn test:ci --shard=$CI_NODE_INDEX/$CI_NODE_TOTAL
但优化后作业仍需20分钟,计划启用Jest缓存。若使用'.jest-cache-${CI_COMMIT_REF_SLUG}-${CI_NODE_INDEX}'作为缓存键,每个分支会生成4个包含大量重复内容(主要是转换后的npm包)的缓存,占用过多存储空间,需要合理的缓存键设置方案。
优化方案
1. 拆分公共缓存与分片专属缓存
Jest的缓存分为公共依赖缓存(转换后的npm包、第三方库)和分片专属缓存(当前分片测试文件的转换结果)两部分,可拆分分别缓存:
公共缓存配置
针对所有分片共享的依赖部分,使用不包含CI_NODE_INDEX的键,避免重复缓存公共内容:
cache: key: '.jest-cache-common-${CI_COMMIT_REF_SLUG}-${CI_JOB_IMAGE}-${CI_YARN_VERSION}' paths: - .jest-cache/cache/transformers/ - .jest-cache/cache/modules/
加入CI_JOB_IMAGE和CI_YARN_VERSION是为了避免不同运行环境(如不同Node版本镜像、依赖安装版本)的缓存冲突。
分片专属缓存配置
针对每个分片独有的测试文件转换结果,保留包含CI_NODE_INDEX的键:
cache: key: '.jest-cache-shard-${CI_COMMIT_REF_SLUG}-${CI_NODE_INDEX}' paths: - .jest-cache/cache/fs/
fs目录下主要是当前分片测试文件的缓存,各分片内容差异大,适合单独缓存。
2. 基础键+回退缓存(推荐)
如果不想拆分缓存路径,可使用分支+依赖哈希作为基础公共键,再通过GitLab的缓存回退机制让分片共享公共缓存:
cache: key: '.jest-cache-${CI_COMMIT_REF_SLUG}-${CI_NODE_INDEX}' fallback_keys: - '.jest-cache-${CI_COMMIT_REF_SLUG}-${NODE_MODULES_HASH}' - '.jest-cache-${CI_COMMIT_REF_SLUG}' paths: - .jest-cache/ variables: NODE_MODULES_HASH: $(sha256sum yarn.lock | cut -d ' ' -f 1)
每个分片优先使用自身缓存,不存在则回退到分支公共缓存;加入yarn.lock的哈希值,能确保依赖变更时自动更新公共缓存,避免缓存失效不及时的问题。
3. 全局公共缓存+分支覆盖
如果多分支依赖差异不大,可设置全局公共缓存作为默认,分支缓存覆盖特有内容,分片缓存存储独有的测试缓存:
cache: key: '.jest-cache-${CI_COMMIT_REF_SLUG}-${CI_NODE_INDEX}' fallback_keys: - '.jest-cache-global-${CI_JOB_IMAGE}' - '.jest-cache-global' paths: - .jest-cache/
全局缓存存储所有分支共享的依赖转换结果,最大程度减少重复缓存内容。
额外优化建议
- 确保Jest配置开启缓存:在
jest.config.js中设置cache: true,并指定缓存目录cacheDirectory: '.jest-cache'。 - 定期清理过期缓存:在GitLab项目设置中配置缓存过期时间,避免长期占用存储空间。
内容的提问来源于stack exchange,提问作者Rupert Chen
相关产品推荐
相关产品推荐

