ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Nx 任务缓存完全指南:从哈希计算、远程缓存到 inputs/outputs 精细调优

2026/9/10 1:20:08 拓冰建站 浏览量
Nx 任务缓存完全指南:从哈希计算、远程缓存到 inputs/outputs 精细调优 Nx 任务缓存完全指南从哈希计算、远程缓存到 inputs/outputs 精细调优【免费下载链接】nxThe Monorepo Platform that amplifies both developers and AI agents. Nx optimizes your builds, scales your CI, and fixes failed PRs automatically. Ship in half the time.项目地址: https://gitcode.com/GitHub_Trending/nx/nxNx 内置了一套久经实战考验battle-tested的计算缓存computation caching系统确保同一份代码永远不会被重复构建两次。本文以 Nx 官方 Explore Nx 课程中的《Cache Task Results》一课对应课程文档 03-cache-task-results.md为核心骨架结合仓库内完整的官方功能文档 cache-task-results.mdoc、缓存原理文档与源码实现系统讲解任务缓存的配置方法、底层哈希机制、远程缓存接入以及排错手段。读完本文你将能够在本仓库的 Monorepo 工作区中准确配置可缓存任务、用 inputs/outputs 精准控制缓存命中率并让本地与 CI 的构建速度都得到显著提升。为什么需要任务缓存在现代前端与后端 Monorepo 中反复构建、重跑测试同一份代码的成本非常高。Nx 的缓存系统解决了两个核心痛点大幅缩短任务执行时间在本地开发与 CI 中命中的任务直接跳过执行从缓存恢复结果降低 CI/CD 费用缓存命中的任务不再真正执行从而减少需要消耗的 CI 计算资源。Nx 在命中缓存时不仅恢复终端输出terminal output还会恢复任务运行产生的文件例如build或dist目录。这意味着你得到的不只是一行“Cached”的提示而是完整的、可直接使用的构建产物。缓存的工作原理一次任务如何命中缓存要理解缓存配置先要理解 Nx 在底层如何判定“两次运行是否等价”。仓库中的 how-caching-works.mdoc 给出了权威解释在运行一个可缓存任务之前Nx 会根据任务的inputs计算一个哈希值hash。两个具有相同哈希的运行代表相同的计算因此 Nx 可以安全地复用之前的结果。任务哈希的组成可以包括项目源文件以及项目依赖dependencies的文件相关的工作区配置workspace configuration外部依赖external dependencies的版本运行时值例如操作系统与 CPU 架构传给任务的命令行参数command-line arguments。缓存查找与存储流程Nx 的缓存查找遵循“先本地、后远程”的顺序计算任务哈希先查询本地缓存若本地未命中且配置了远程缓存再查询远程缓存命中则恢复缓存的输出文件并回放存储的终端输出未命中则真正执行任务并把终端输出和配置的 outputs 文件存入本地缓存若配置了远程缓存且鉴权允许写入还会同步写入远程缓存。Nx 会独立处理任务图task graph中的每个节点因此同一个任务图中可以出现“部分任务命中缓存、部分任务正常执行”的混合状态这在大型 CI 中非常常见。缓存条目里到底存了什么一个缓存条目cache entry包含三部分写入标准输出stdout和标准错误stderr的终端输出被目标target的outputs配置匹配到的文件与目录用于标识该条目的任务哈希。值得强调的是Nx 不会把源文件等 inputs 存进缓存条目它们只通过自身的哈希参与任务哈希的计算。定义可缓存任务在 Nx 中任务默认并不会被缓存你需要显式声明哪些任务是可缓存的。最简单的方式是在工作区根目录的nx.json中通过targetDefaults为某一类目标任务开启缓存// nx.json { targetDefaults: { build: { cache: true }, test: { cache: true } } }上面的配置会让工作区内所有名为build和test的目标targets启用缓存。可缓存操作必须是“无副作用”的⚠️可缓存操作需要是副作用无关side effect free的给定相同的输入它必须总是产生相同的输出。例如会真实请求后端 API 的 e2e 测试不能被缓存因为后端状态可能影响测试结果。如果缓存了这类任务你可能会在 CI 中得到“假阳性”的测试通过结果。开启远程缓存让 CI 共享缓存默认情况下Nx 只在本地缓存任务结果。远程缓存的价值在于在不同的 CI 运行之间共享缓存例如开发者本地的一次构建结果可以直接被 CI 复用反之亦然。Nx 提供了基于 Nx Cloud 的托管式远程缓存方案。连接你的工作区到 Nx Cloud 只需一条命令npx nxlatest connect连接之后本地与 CI 的任务结果会写入远程缓存任何一次构建、测试的产出都能被所有协作者和 CI 流水线复用。更详细的机制可以参考仓库中的 remote-cache.mdoc。用 inputs 与 outputs 精细调优缓存Nx 缓存开箱即用的默认值已经比较合理但在实际工程中你几乎总是需要微调默认值精确控制“什么变化会触发缓存失效”。控制缓存的两个核心选项是Inputs输入定义哪些内容参与哈希计算例如文件、环境变量等。只要任一 input 发生变化缓存即失效任务会重新执行Outputs输出定义任务执行后会在哪些目录/文件产生产物这些产物会被缓存并在命中时恢复。这两类配置既可以定义在项目级project.json或package.json的nx字段中也可以定义在全局nx.json对所有项目生效。一个完整的调优示例假设我们想让build任务忽略所有*.md文件——即修改README.md等 Markdown 文件时不应使构建缓存失效同时我们知道构建产物会输出到工作区根目录dist下以项目名命名的文件夹中。以下给出全局与项目级两种配置方式方式一全局配置nx.json对所有项目生效// nx.json { targetDefaults: { build: { inputs: [{projectRoot}/**/*, !{projectRoot}/**/*.md], outputs: [{workspaceRoot}/dist/{projectName}] } } }方式二项目级配置project.json// packages/some-project/project.json { name: some-project, targets: { build: { ... inputs: [!{projectRoot}/**/*.md], outputs: [{workspaceRoot}/dist/apps/some-project], ... } ... } }方式三项目级配置package.json对于基于package.json配置 Nx 的项目同样可以把配置放在nx字段下// packages/some-project/package.json { name: some-project, nx: { targets: { build: { ... inputs: [!{projectRoot}/**/*.md], outputs: [{workspaceRoot}/dist/apps/some-project], ... } ... } } }注意只有当输出位置与默认的dist或build目录不同时才需要显式定义 outputs——Nx 会自动识别常规的dist、build目录。认识 inputs 的书写语法与占位符从 configure-inputs.mdoc 可以提炼出 inputs 书写的关键规则目录路径需要尾部斜杠或 glob指定目录作为 input 时必须写成{projectRoot}/src/或{projectRoot}/src/**/*形式写成{projectRoot}/src无尾部斜杠不会匹配任何文件。这一点与 outputs 不同——outputs 支持裸目录路径。常用占位符{projectRoot}项目根目录{workspaceRoot}工作区根目录只能出现在 output 的起始位置{projectName}项目名{options.outputPath}引用任务 options 中定义的路径适合输出位置由选项决定的场景。!前缀表示排除例如!{projectRoot}/**/*.md从输入集中剔除 Markdown 文件。namedInputs复用输入集合当多个目标需要共享同一套输入定义时可以在nx.json中定义namedInputs。这是 Nx 官方实践中推荐的做法// nx.json { namedInputs: { default: [{projectRoot}/**/*, sharedGlobals], production: [ default, !{projectRoot}/jest.config.ts, !{projectRoot}/**/?(*.)(spec|test).ts, ], }, }配合namedInputs之后构建类插件如nx/webpack/plugin、nx/vite/plugin通常会为编译/打包任务推断出inputs: [ production, // 项目内除测试文件外的所有文件 ^production // 依赖中可能影响本项目的输入 ]而测试类插件如nx/cypress/plugin、nx/playwright/plugin、nx/jest/plugin会推断出inputs: [ default, // 项目内全部文件含测试文件 ^production ]^前缀表示“该命名输入在项目依赖上的版本”。这样配置后Nx 的行为是只改动测试文件时Nx 从缓存恢复之前的编译结果仅重跑受影响项目的测试改动任何生产文件时Nx 会重跑该项目及其依赖者的测试。把运行时信息纳入哈希sharedGlobals很多情况下语言运行时版本会影响所有任务的输出。此时可以借助sharedGlobals命名输入把运行时命令的输出纳入每一个任务的哈希。例如让所有任务的哈希都考虑 Node.js 版本// nx.json { namedInputs: { default: [{projectRoot}/**/*, sharedGlobals], sharedGlobals: [{ runtime: node --version }] } }命令行参数也会影响哈希因为参数可能改变运行结果传给任务的命令行参数同样参与哈希计算。例如下面两条命令会产生不同的哈希nx build myapp nx build myapp --sourcemap反过来只要最终构成的任务与任务参数一致不同形式的 Nx 命令会产生相同的哈希可以互相命中缓存nx build myapp nx run-many -t build -p myapp当对多个项目运行同一目标时Nx 会为每个任务分别计算哈希因此可能出现“A 项目从缓存恢复、B 项目真实执行”的情况。让插件自动配置缓存手动维护 inputs/outputs 难免有疏漏而Nx 插件可以根据底层工具的配置文件自动推断任务并配置缓存。这是 Nx 的推荐路径——官方文档明确说明使用 Nx plugins 时很多任务的缓存配置都是自动完成的省去了手工配置的负担。例如执行下面的命令安装nx/vite插件npx nx add nx/vite插件会自动检测工作区中的vite.config.ts文件推断出你可以运行的build等任务并自动配置这些任务的缓存设置以及任务流水线task pipeline例如触发依赖项目的构建。这意味着你无需手工声明 Vite 任务的缓存且 inputs、outputs 始终与vite.config.ts保持同步。查看插件自动配置的任务设置想查看某个项目被插件自动配置的任务详情可以运行nx show project project-name --web该命令会在浏览器中打开 Project Details 视图展示每个任务的 inputs、outputs、cache 状态以及来源source map 会标明配置来自哪个插件或哪个配置文件。也可以安装 Nx Console编辑器扩展参考 editor-setup.mdoc直接在 IDE 中查看。此外运行任务时加上--graph标志可以打开任务图task graph点击某个任务即可查看其全部 inputs 列表nx build myreactapp --graph缓存相关的命令行操作日常开发中以下命令与缓存直接相关详见 skipping-cache.mdoc场景命令效果跳过缓存强制重新执行npx nx build --skip-nx-cache不使用任何本地/远程缓存任务必定真实执行使用 Nx Cloud 时该次运行也不会被记录跳过 Nx Cloud 远程缓存npx nx build --no-cloud不使用远程缓存结果但仍然使用本地缓存如有清空本地缓存并重置npx nx reset清除本地缓存与工作区元数据并关闭 Nx Daemon其中--skip-nx-cache等命令行选项的实现在仓库的 command-object.ts 与共享选项定义 shared-options.ts 中对应的 schema 声明可在 nx-schema.json 中查看。故障排查缓存没有命中怎么办缓存配置出问题时最典型的现象是“任务被真正执行了而我以为它会从缓存恢复”。仓库中的 troubleshoot-cache-misses.mdoc 提供了系统的排查思路确认任务被标记为可缓存运行nx show project project-name --web查看 Project Details 视图中任务是否带有 “Cacheable” 标签检查目标的配置中是否设置了cache: true在项目project.json或nx.json#targetDefaults中。检查 outputs 是否污染了 inputs审查项目配置与根nx.json中定义的inputs/namedInputs重点检查是否有某个输出文件没有被outputs捕获——outputs只控制“从缓存恢复哪些文件”并不会决定“是否恢复缓存”但未登记的输出文件可能反过来修改了某个 input从而持续导致缓存失效。逐文件核对输入 glob运行nx graph --fileoutput.json导出项目关联文件清单或直接在nx graph可视化中点击任务查看。使用 Nx Cloud 的对比工具确保仓库已连接 Nx Cloud点击终端输出的 run details 链接按缓存状态筛选任务打开任务详情后点击 “Compare to similar tasks”Nx Cloud 会对比两次运行的哈希输入并高亮所有差异。注意Nx Cloud 无法读取你的源码只能基于保存的内容哈希告诉你“哪些输入不同”而无法给出源码层面的 git diff。结语与延伸阅读任务缓存是 Nx 作为 Monorepo 平台最核心的能力之一——它直接支撑了“只跑受影响任务”“CI 分钟数减半”等效率目标。结合本仓库的文档体系你可以继续深入缓存概念模型how-caching-works.mdoc缓存配置实操教程caching.mdocinputs 深入配置configure-inputs.mdocoutputs 深入配置configure-outputs.mdoc修改缓存位置change-cache-location.mdoc远程缓存与 CIremote-cache.mdoc把“先定义可缓存任务、再用 inputs/outputs 精准控制哈希、最后接入远程缓存共享 CI 结果”这条链路打通你的 Monorepo 就能真正享受“代码永不重复构建”的红利。【免费下载链接】nxThe Monorepo Platform that amplifies both developers and AI agents. Nx optimizes your builds, scales your CI, and fixes failed PRs automatically. Ship in half the time.项目地址: https://gitcode.com/GitHub_Trending/nx/nx创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考