
Nx Affected 项目筛选实战用nx show projects --affected精准定位变更影响范围【免费下载链接】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在 Nx Monorepo 中一次代码提交往往只改动少量文件但受影响的项目却可能因依赖链扩散到整个工作区。affected是 Nx 提供的变更影响分析能力它根据当前分支与目标分支或指定提交范围、工作区未提交状态的差异结合项目依赖图精确计算出被变更波及的项目集合。本文以仓库内 AFFECTED.md 为骨架结合 Nx 源码深入讲解nx show projects --affected的完整用法与底层实现读完你可以在本地开发、CI 流水线和脚本中自如地筛选出真正需要构建、测试、部署的项目避免全量任务浪费。核心命令nx show projects --affectednx show projects用于列出工作区中的项目--affected标志让它只输出受当前变更影响的项目。它会自动对比当前 HEAD 与检出分支的公共祖先找出被修改的文件所触及的项目并沿依赖图向上传播把依赖了这些项目的下游项目一并纳入结果。# Affected since base branch (auto-detected) nx show projects --affected不带任何参数时Nx 会尝试自动检测基础分支base ref。从源码看这一自动检测体现在 command-line-utils.ts 的parseFiles与getMergeBase逻辑中若命令行未显式提供--base且设置了环境变量NX_BASE则优先使用该环境变量的值--head同理对应NX_HEAD若仍未提供 base则回退到 Nx 配置的默认基础引用仓库根目录 nx.json 中可配置defaultBase通常为main最终比较范围默认为--basedefaultBase --headHEAD。对 base 值的解析还会做一步找公共祖先处理getMergeBase会依次尝试git merge-base base head失败后回退到git merge-base --fork-point base head最后才直接使用 base 本身。这意味着即使你的分支已落后于main结果也只会包含真正由本次分支变更引入的影响而不是把main上新增的改动全部算进来。显式指定比较范围--base与--head自动检测虽然方便但在 CI 或多人协作场景下显式指定 base 更可控# Affected with explicit base nx show projects --affected --basemain nx show projects --affected --baseorigin/main # Affected between two commits nx show projects --affected --baseabc123 --headdef456--basemain/--baseorigin/main对比本地 main 或远程跟踪分支origin/main到当前 HEAD 的差异--baseabc123 --headdef456对比任意两个提交之间的差异。base 与 head 都接受 commit SHA、分支名、标签等任何合法的 Git revision只给--base不给--head时head 默认为HEAD源码中getFilesUsingBaseAndHead(base, HEAD)只给--head不给--base时base 仍按上述自动检测逻辑取默认分支。底层通过git diff系列命令git diff --name-only base head拿到变更文件列表再交给 affected 计算管线处理因此凡是 Git 能识别的 revision 写法这里都能用。结合工作区状态--uncommitted与--untracked有些场景你并不关心与远程分支的差异而只想知道手头还没提交的改动会影响谁例如运行本地测试前评估改动面# Affected by uncommitted changes nx show projects --affected --uncommitted # Affected by untracked files nx show projects --affected --untracked--uncommitted基于已修改但未提交含已暂存 staged的文件计算影响--untracked基于尚未被 Git 跟踪的新文件计算影响。在 command-line-utils.ts 的parseFiles实现中文件来源的判定顺序是显式--files--uncommitted--untracked--base/--head组合 默认 base。也就是说这两个标志会跳过与远端分支的比较直接从 Git 工作区状态提取变更。若同时存在未提交改动和未跟踪文件--uncommitted只覆盖前者--untracked只覆盖后者可按需组合使用。裁剪结果集--type、--exclude与组合筛选实际执行任务时受影响的项目往往还需要进一步过滤比如只关心应用、或把 e2e 项目排除在外# Affected apps only nx show projects --affected --type app # Affected excluding e2e projects nx show projects --affected --exclude*-e2e--type接受app、lib、e2e等 projectType按项目类型裁剪。showProjectsHandler在拿到 affected 图后会先用filterNodes过滤掉类型不匹配的节点见 projects.ts--exclude支持 glob 模式如*-e2e、项目名、tag 引用如tag:internal以及取反写法。源码中排除逻辑通过findMatchingProjects解析模式后从结果集中剔除由于showProjectsHandler中 affected 处理最先执行、随后才是类型过滤、-p/--projects过滤、--withTarget过滤和--exclude剔除因此它们可以自由叠加例如# 受影响的 lib且具备 test target nx show projects --affected --type lib --withTarget test # 受影响的 app排除私有项目 nx show projects --affected --type app -p !tag:private输出与脚本集成--json与编程式消费nx show projects --affected默认每行输出一个项目名。需要被脚本或 Agent 消费时使用--json获取结构化数组再交给jq等工具处理# 受影响项目数组 nx show projects --affected --json | jq . # 统计数量 nx show projects --affected --json | jq length # 只取名字前缀匹配的项目 nx show projects --affected --json | jq .[] | select(startswith(shared-))这与 SKILL.md 中始终使用--json获取结构化输出用命令行工具编程式计算而非人工计数的建议一致。在 CI 中你可以把输出直接喂给nx run-many --projects$(...)或逐项目触发构建实现只跑受影响的包。依赖图上的传递闭包affected 的底层原理理解了命令用法后再看 Nx 是如何从变更文件得到受影响项目集合的。核心实现在 affected-project-graph.ts 的filterAffected中整个过程分两步第一步从变更文件定位被触碰的项目touched projects。filterAffected内部维护了一个 locator 数组逐个执行并合并结果getTouchedProjects见 workspace-projects.ts将变更文件路径映射到项目根目录直接命中文件属于哪个项目getImplicitlyTouchedProjects处理隐式依赖。它内置了nx.json: *规则——任何nx.json的改动会波及所有项目同时还会扫描各 target 的inputs与namedInputs凡是以{workspaceRoot}/开头的全局文件如根级babel.config.json、CI 配置文件等一旦变化也会标记为对应项目的隐式触碰getTouchedProjectsFromProjectGlobChanges项目级 glob 变更如project.json、目录结构变化getJSTouchedProjects见 touched-projects.tsJS/TS 生态专属检测聚合了 lockfile 变更lock-file-changes、npm 包依赖变更npm-packages与tsconfig.json变更tsconfig-json-changes三类 locator。第二步沿反向依赖图传播。filterAffectedProjects会先将项目图做反转reverse(graph)再从每个 touched project 出发做深度遍历凡是依赖了被触碰项目的项目都会被标记为受影响同时保留它们之间的依赖边。实现上使用两个共享的visitedSet一个管节点、一个管依赖边确保多个 touched project 共享的下游依赖只被遍历一次避免O(touched × 共享依赖)的重复计算。最终产出一个只包含受影响节点与其依赖关系的子图。这条管线在nx affected批量执行任务与nx show projects --affected仅列出项目两个入口中共享。前者见 affected.ts 的getAffectedGraphNodes先用filterAffected过滤出受影响项目再筛掉不含指定 target 的项目后交给runCommand执行后者见 projects.ts 的showProjectsHandler先构建 affected 图再做类型、target、exclude 等裁剪后输出。隐式影响为何改一个根配置文件会波及全仓理解 affected 时最容易被忽略的是隐式影响。除显式 import 关系外Nx 认为以下文件变更会影响项目nx.json被硬编码为影响所有项目nx.json: *targetinputs/namedInputs中以{workspaceRoot}/声明的全局文件例如仓库根目录 nx.json 的sharedGlobals中列出的babel.config.json、.github/workflows/ci.yml等一旦这些文件变更使用该 input 定义的所有项目的对应 target 都被视为受影响锁文件lockfile、根级tsconfig.json、被依赖的 npm 包版本变化由 JS 生态 locator 检测凡是受这些全局变更影响的项目都会被标记。因此当你在 CI 中看到只改了一个配置文件却触发了很多项目重建时不必惊讶——这恰恰是 Nx 保守但正确的取舍宁可多跑也不放过可能受全局配置影响的构建。常见场景速查场景命令对比默认分支的所有变更nx show projects --affected对比远程 mainnx show projects --affected --baseorigin/main对比两个提交nx show projects --affected --baseabc123 --headdef456只看受影响的应用nx show projects --affected --type app排除 e2e 项目nx show projects --affected --exclude*-e2e基于未提交改动nx show projects --affected --uncommitted基于未跟踪文件nx show projects --affected --untracked输出 JSON 供脚本消费nx show projects --affected --json组合建议在 CI 中固定使用--baseorigin/main或合并请求的目标分支保证可复现在本地快速验证时优先--uncommitted在脚本中一律加--json并通过jq处理。若 nx 未全局安装可参考 SKILL.md 的建议用npx nx/pnpm nx等前缀执行。掌握了nx show projects --affected你就掌握了 Nx 增量构建、增量测试与精准 CI 的入口。【免费下载链接】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),仅供参考