前言:一个反直觉的问题
说到缓存,多数人的直觉是"文件没变,缓存就有效"。但 monorepo 的任务缓存远没有这么简单。
试想一个场景:你改了@platform/utils的src/format.ts,加了 3 行代码。构建工具告诉你 9 个包"缓存失效,需要重新构建"。你查了一下,其中 6 个包的src/目录一行没动。
为什么没改代码的包也要重新构建?
答案藏在缓存 key 的计算逻辑里。一个构建任务的缓存 key,由六个维度的输入共同决定。这篇文拆解它的每一层。
核心机制:六维 Hash 计算流程
整个流程可以概括为一个函数签名:
fn compute_task_hash(task: &TaskConfig, env: &EnvSnapshot) -> HashOutput { let mut hasher = Hasher::new(); hasher.input(FILE_HASH); // 第一层:源文件 hasher.input(DEPENDENCY_HASH); // 第二层:依赖任务 hasher.input(EXTERNAL_DEPS_HASH); // 第三层:外部依赖 hasher.input(ENV_HASH); // 第四层:环境变量 hasher.input(TASK_CONFIG_HASH); // 第五层:任务配置 hasher.input(GLOBAL_HASH); // 第六层:全局哈希 hasher.finalize() }下面逐层拆解。
第一层:文件哈希(File Hash)
这是最直观的一层,但细节并不简单。
配置里inputs字段定义了哪些文件参与 hash:
{"build":{"inputs":["src/**","tsconfig.json","package.json"]}}<