为什么Shake二次构建未执行生成逻辑却将_build/b标记为已变更
原因分析
- 首先是
alwaysRerun内置规则的特性:它设计上就会在每次构建时标记为changed,不管实际是否有变更,通常用于每次构建都需要重新检查的场景(比如读取环境变量、查询外部系统状态)。 - 你的
_build/a规则显式依赖了alwaysRerun,因此每次构建都会执行_build/a的生成逻辑,但是你用了writeFileChanged写入内容:该函数会对比现有文件内容和待写入内容,只有内容不同时才会写入更新,因此第二次构建时_build/a内容没有变化,被正确标记为unchanged。 - 至于
_build/b被误标记为changed,是Shake的变更传播保守策略导致的:_build/b的传递依赖链中存在标记为changed的alwaysRerun节点,且_build/b本身在本次构建中没有被执行,也没有显式的内容校验结果证明输出没有变化,因此Shake保守判定它为changed,避免遗漏真正需要更新的场景。
修复方案
- 方案1:开启内容哈希校验,在
shakeOptions中添加配置shakeChange = ChangeDigest,Shake会计算输出文件的内容哈希判断是否真的发生变更,只要文件内容和上次构建一致,哪怕传递依赖有变更标记,也会标记为unchanged。 - 方案2:修改
_build/b的生成逻辑,用writeFileChanged代替普通的writeFile写入文件,Shake会记录输出的预期内容,辅助变更判断。 - 方案3:如果
alwaysRerun不是必须的,替换为你实际需要的检查逻辑,从源头避免不必要的变更标记传递。
内容的提问来源于stack exchange,提问作者Cactus
相关产品推荐
相关产品推荐

