Nx Monorepo 工作区模式实战nx.json 任务编排、模块边界与 Affected CI 优化全解【免费下载链接】agentsMulti-harness agentic plugin marketplace for Claude Code, Codex, Cursor, OpenCode, GitHub Copilot, and Google Antigravity项目地址: https://gitcode.com/GitHub_Trending/agents24/agents本指南以plugins/developer-essentials/skills/nx-workspace-patterns技能包为核心系统讲解 Nx monorepo 的完整配置模板与落地实践从nx.json全局任务编排、project.json单项目目标定义到基于 tag 的模块边界强制约束、自定义 generator 的代码生成以及利用 affected 命令与远程缓存优化 CI 的全套方案。读完本文你将能够从零搭建一套具备缓存、增量构建、依赖约束与 CI 加速能力的生产级 Nx 工作区并理解每一段配置背后的执行原理。技能定位这份文档在仓库中的作用在 developer-essentials 插件中nx-workspace-patterns技能SKILL.md面向设置 Nx 工作区、配置项目边界、优化构建缓存、落地 affected 命令等场景其导航层给出了架构图与最佳实践而 references/details.md 则承载了 6 套可直接复制的配置模板与常用命令清单——这正是本文的主体骨架。它与同目录下的 monorepo-management 技能互补后者覆盖 pnpm workspaces、Turborepo、共享配置与发布流程是多工具横向视角前者则是 Nx 专属的纵深配置手册。配套的 monorepo-architect Agent 提供了 8 步工作流评估代码库 → 选型 → 设计结构 → 缓存策略 → affected 检测 → 任务管线 → 远程缓存 → 文档化约定本指南中的模板即服务于该工作流的落地执行。Nx 工作区架构与库类型划分标准目录结构从 SKILL.md 可以看出一个典型 Nx 工作区遵循以下结构workspace/ ├── apps/ # Deployable applications │ ├── web/ │ └── api/ ├── libs/ # Shared libraries │ ├── shared/ │ │ ├── ui/ │ │ └── utils/ │ └── feature/ │ ├── auth/ │ └── dashboard/ ├── tools/ # Custom executors/generators ├── nx.json # Nx configuration └── workspace.json # Project configurationapps/可部署的应用入口web、api 等是依赖图的叶子消费端libs/按职责拆分的共享库是复用的核心单元tools/存放自定义 executor执行器与 generator代码生成器nx.json工作区级配置本文 Template 1 详解project.json单项目级配置本文 Template 2 详解。库的职责分层类型用途示例feature智能组件、业务逻辑feature-authui展示型组件ui-buttonsdata-accessAPI 调用、状态管理data-access-usersutil纯函数、工具方法util-formattingshell应用引导装配shell-web这套分层是后面模块边界规则Template 3得以成立的前提——每一层只允许依赖其下层从而保证依赖图无环、依赖方向可控。Template 1nx.json 全局配置逐字段解析nx.json是 Nx 工作区的大脑统一定义任务缓存、输入指纹与依赖顺序。模板全文如下{ $schema: ./node_modules/nx/schemas/nx-schema.json, npmScope: myorg, affected: { defaultBase: main }, tasksRunnerOptions: { default: { runner: nx/tasks-runners/default, options: { cacheableOperations: [ build, lint, test, e2e, build-storybook ], parallel: 3 } } }, targetDefaults: { build: { dependsOn: [^build], inputs: [production, ^production], cache: true }, test: { inputs: [default, ^production, {workspaceRoot}/jest.preset.js], cache: true }, lint: { inputs: [default, {workspaceRoot}/.eslintrc.json], cache: true }, e2e: { inputs: [default, ^production], cache: true } }, namedInputs: { default: [{projectRoot}/**/*, sharedGlobals], production: [ default, !{projectRoot}/**/?(*.)(spec|test).[jt]s?(x)?(.snap), !{projectRoot}/tsconfig.spec.json, !{projectRoot}/jest.config.[jt]s, !{projectRoot}/.eslintrc.json ], sharedGlobals: [ {workspaceRoot}/babel.config.json, {workspaceRoot}/tsconfig.base.json ] }, generators: { nx/react: { application: { style: css, linter: eslint, bundler: webpack }, library: { style: css, linter: eslint }, component: { style: css } } } }各字段的核心作用npmScope为工作区内的包提供统一前缀如myorg/web配合 TS 路径映射使用保证跨项目导入路径一致。affected.defaultBase指定 affected 命令的默认对比基线分支main。执行nx affected -t test时Nx 会比较当前 HEAD 与defaultBase之间的变更只运行受影响的项目的任务。这也是 CI 中只测改动的这一核心加速手段的默认锚点。tasksRunnerOptions.default任务执行器的配置。runner: nx/tasks-runners/default使用默认执行器本地缓存 进程并行cacheableOperations声明哪些操作可被缓存。注意e2e、build-storybook也被列入了缓存集合——只要输入指纹未变Nx 会直接重放上次的产物而不是重新执行parallel: 3控制并行执行的任务数CI 上可结合机器资源调大模板 5 的 CI 中--parallel3即与此呼应。targetDefaults为所有项目的同名 target 提供默认值避免在每个project.json中重复声明。dependsOn: [^build]语义为先构建我依赖的所有项目^表示上游依赖从而保证跨项目拓扑排序inputs定义该任务的缓存指纹由哪些文件决定详见namedInputscache: true显式开启该 target 的缓存。namedInputs命名一组文件集合供inputs引用是整个缓存命中率的关键设计default{projectRoot}/**/*项目全部文件加上sharedGlobalsproduction在default基础上用!排除测试文件、快照、tsconfig.spec.json、jest.config与.eslintrc.json——也就是说仅修改测试相关文件不会使build缓存失效sharedGlobals把babel.config.json、tsconfig.base.json这类改一处影响全局的根级文件提升为全局输入任何一处变化都会正确触发下游重算。generators为生成器预设默认参数如 React 应用默认webpackeslintcss保证团队内脚手架产物风格统一。从实现角度看inputs与namedInputs决定了 Nx 计算任务哈希的文件范围哈希命中即命中缓存这也是 Nx 相比全量构建 时间戳判断更快的原因。若把production中排除的测试文件误删或把依赖文件排除出default就会造成缓存误命中改代码不重跑或误失效没改代码却重跑因此namedInputs是缓存调优的第一着力点。Template 2project.json 单项目目标定义每个项目应用或库通过project.json声明自己的 targets。以apps/web为例// apps/web/project.json { name: web, $schema: ../../node_modules/nx/schemas/project-schema.json, sourceRoot: apps/web/src, projectType: application, tags: [type:app, scope:web], targets: { build: { executor: nx/webpack:webpack, outputs: [{options.outputPath}], defaultConfiguration: production, options: { compiler: babel, outputPath: dist/apps/web, index: apps/web/src/index.html, main: apps/web/src/main.tsx, tsConfig: apps/web/tsconfig.app.json, assets: [apps/web/src/assets], styles: [apps/web/src/styles.css] }, configurations: { development: { extractLicenses: false, optimization: false, sourceMap: true }, production: { optimization: true, outputHashing: all, sourceMap: false, extractLicenses: true } } }, serve: { executor: nx/webpack:dev-server, defaultConfiguration: development, options: { buildTarget: web:build }, configurations: { development: { buildTarget: web:build:development }, production: { buildTarget: web:build:production } } }, test: { executor: nx/jest:jest, outputs: [{workspaceRoot}/coverage/{projectRoot}], options: { jestConfig: apps/web/jest.config.ts, passWithNoTests: true } }, lint: { executor: nx/eslint:lint, outputs: [{options.outputFile}], options: { lintFilePatterns: [apps/web/**/*.{ts,tsx,js,jsx}] } } } }理解 target 的三层结构executor指明执行该 target 的工具包如nx/webpack:webpack、nx/jest:jest、nx/eslint:lint。executor 是 Nx 抽象构建步骤的方式——同一个buildtarget 可以在不同项目里换成不同 executor如 vite 或 rollup而命令入口nx build web保持一致。outputs声明任务的产物路径如dist/apps/web、覆盖率目录。Nx 缓存的是 outputs 指向的产物而非源码缓存重放时也会把产物恢复到该路径。configurations为同一 target 提供多套参数组合。build默认走productiondefaultConfigurationserve默认走development。生产配置开启optimization、outputHashing: all资源带内容哈希利于缓存、extractLicenses抽取许可证文件开发配置关闭优化、开启 sourceMap兼顾构建速度与调试体验。tags项目的属性标签如type:app与scope:web。标签本身没有行为只有被 Template 3 的边界规则引用后才产生约束力。Template 3基于 tag 的模块边界规则模块边界是 Nx 治理依赖混乱的核心武器它让哪一层能依赖哪一层从口头约定变成 CI 中可强制执行的错误。模板位于工作区根.eslintrc.json// .eslintrc.json { root: true, ignorePatterns: [**/*], plugins: [nx], overrides: [ { files: [*.ts, *.tsx, *.js, *.jsx], rules: { nx/enforce-module-boundaries: [ error, { enforceBuildableLibDependency: true, allow: [], depConstraints: [ { sourceTag: type:app, onlyDependOnLibsWithTags: [ type:feature, type:ui, type:data-access, type:util ] }, { sourceTag: type:feature, onlyDependOnLibsWithTags: [ type:ui, type:data-access, type:util ] }, { sourceTag: type:ui, onlyDependOnLibsWithTags: [type:ui, type:util] }, { sourceTag: type:data-access, onlyDependOnLibsWithTags: [type:data-access, type:util] }, { sourceTag: type:util, onlyDependOnLibsWithTags: [type:util] }, { sourceTag: scope:web, onlyDependOnLibsWithTags: [scope:web, scope:shared] }, { sourceTag: scope:api, onlyDependOnLibsWithTags: [scope:api, scope:shared] }, { sourceTag: scope:shared, onlyDependOnLibsWithTags: [scope:shared] } ] } ] } } ] }规则如何生效nx/enforce-module-boundaries规则会读取每个项目project.json中的tags再按depConstraints检查依赖方向按职责分层type:*type:app可依赖 feature/ui/data-access/utiltype:feature不可再依赖其他 feature避免业务逻辑互串只能依赖 ui/data-access/utiltype:ui只能依赖 ui 与 utiltype:data-access只能依赖>// tools/generators/feature-lib/index.ts import { Tree, formatFiles, generateFiles, joinPathFragments, names, readProjectConfiguration, } from nx/devkit; import { libraryGenerator } from nx/react; interface FeatureLibraryGeneratorSchema { name: string; scope: string; directory?: string; } export default async function featureLibraryGenerator( tree: Tree, options: FeatureLibraryGeneratorSchema, ) { const { name, scope, directory } options; const projectDirectory directory ? ${directory}/${name} : libs/${scope}/feature-${name}; // Generate base library await libraryGenerator(tree, { name: feature-${name}, directory: projectDirectory, tags: type:feature,scope:${scope}, style: css, skipTsConfig: false, skipFormat: true, unitTestRunner: jest, linter: eslint, }); // Add custom files const projectConfig readProjectConfiguration( tree, ${scope}-feature-${name}, ); const projectNames names(name); generateFiles( tree, joinPathFragments(__dirname, files), projectConfig.sourceRoot, { ...projectNames, scope, tmpl: , }, ); await formatFiles(tree); }组合式生成的实现思路Schema 接口FeatureLibraryGeneratorSchema声明入参name、scope与可选的directory生成器的参数校验与 CLI 提示都基于它。复用官方生成器先调用libraryGenerator来自nx/react生成标准库骨架同时通过tags: type:feature,scope:${scope}自动打上符合 Template 3 约束的标签保证生成即合规。模板文件注入利用generateFiles把files/目录下的模板文件支持__tmpl__后缀与模板插值注入到projectConfig.sourceRootnames()工具负责把 kebab-case 名称转换成 camelCase、PascalCase 等变体供模板使用。收尾格式化formatFiles(tree)统一运行 prettier保证生成代码风格一致。执行时只需nx g feature-lib --nameauth --scopeweb即可得到带正确目录、标签、测试与 lint 配置的完整 feature 库避免手写带来的目录漂移。Template 5用 Affected 命令优化 CI 流水线CI 是全量构建的重灾区。模板给出的 GitHub Actions 工作流.github/workflows/ci.yml只对受影响的项目执行任务# .github/workflows/ci.yml name: CI on: push: branches: [main] pull_request: branches: [main] env: NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }} jobs: main: runs-on: ubuntu-latest steps: - uses: actions/checkoutv4 with: fetch-depth: 0 - uses: actions/setup-nodev4 with: node-version: 20 cache: npm - name: Install dependencies run: npm ci - name: Derive SHAs for affected commands uses: nrwl/nx-set-shasv4 - name: Run affected lint run: npx nx affected -t lint --parallel3 - name: Run affected test run: npx nx affected -t test --parallel3 --configurationci - name: Run affected build run: npx nx affected -t build --parallel3 - name: Run affected e2e run: npx nx affected -t e2e --parallel1三个关键细节fetch-depth: 0affected 命令需要完整的 git 历史来计算从 base 到 head 改了哪些项目。浅克隆默认 fetch 深度 1会导致 Nx 找不到对比基线。nrwl/nx-set-shasv4官方 action 负责从 CI 环境推导出正确的 base/head SHAPR 场景取目标分支与合并基并写入环境变量供后续nx affected消费。分级并行度lint/test/build 使用--parallel3提升吞吐e2e 用--parallel1串行执行——端到端测试常占用浏览器、端口等共享资源过高的并行度反而会引入不稳定。受益于 Template 1 的缓存配置与NX_CLOUD_ACCESS_TOKEN对应 Template 6 的远程缓存未受影响的项目的任务在 CI 中直接命中远程缓存整体流水线时间与改动范围成正比而非与仓库规模成正比。Template 6本地缓存之外——Nx Cloud 与自托管 S3 缓存Nx Cloud 远程缓存// nx.json with Nx Cloud { tasksRunnerOptions: { default: { runner: nx-cloud, options: { cacheableOperations: [build, lint, test, e2e], accessToken: your-nx-cloud-token, parallel: 3, cacheDirectory: .nx/cache } } }, nxCloudAccessToken: your-nx-cloud-token }将 runner 切换为nx-cloud后任务结果会上传到云端本机跑过一次的任务CI 和同事的机器可以直接拉取产物实现跨机器、跨环境的缓存共享。cacheDirectory指定本地缓存目录默认.nx/cacheToken 建议通过环境变量注入而非硬编码。自托管 S3 缓存// Self-hosted cache with S3 { tasksRunnerOptions: { default: { runner: nx-aws-cache/nx-aws-cache, options: { cacheableOperations: [build, lint, test], awsRegion: us-east-1, awsBucket: my-nx-cache-bucket, awsProfile: default } } } }若不便使用云端服务可通过社区 runnernx-aws-cache/nx-aws-cache将缓存落到自有 S3 桶awsBucket用awsRegion与awsProfile控制访问凭据。注意远程缓存的安全模型基于输入哈希即缓存键因此务必保证namedInputs覆盖所有影响产出的文件含全局配置、环境变量类输入防止缓存串扰。常用命令速查以下命令贯穿日常开发与 CI 场景来自 references/details.md# Generate new library nx g nx/react:lib feature-auth --directorylibs/web --tagstype:feature,scope:web # Run affected tests nx affected -t test --basemain # View dependency graph nx graph # Run specific project nx build web --configurationproduction # Reset cache nx reset # Run migrations nx migrate latest nx migrate --run-migrationsnx g nx/react:lib ...生成库并直接指定目录与标签与 Template 4 的自定义 generator 目标一致——生成时打对标签边界规则才能生效nx affected -t test --basemain手动指定基线执行增量测试等价于 CI 中nx-set-shas推导后的行为nx graph打开交互式依赖图面板快速检查依赖方向与环形依赖nx build web --configurationproduction按 Template 2 中production配置构建单项目nx reset清空本地缓存与 daemon 状态用于排查缓存异常nx migrate latest/nx migrate --run-migrations先分析版本迁移方案再实际执行迁移脚本保证 Nx 升级可控。最佳实践Dos 与 Donts结合 SKILL.md 的沉淀应该做Dos标签一致化 模块边界强制type:*、scope:*标签与enforce-module-boundaries配合把架构约束写成可执行的错误尽早开启缓存Template 1 中声明cacheableOperations与inputs是 CI 提速收益最显著的单项投资保持库的单一职责feature/ui/data-access/util 各司其职避免出现什么都放的杂库统一使用 generator无论是官方生成器还是 Template 4 的自定义生成器保证脚手架与标签的一致性文档化边界让新成员能从目录与nx graph中快速理解依赖规则。不要做Donts不要制造循环依赖依赖图必须保持无环否则缓存、affected 与增量构建都会失去正确性不要跳过 affected全量跑测试会让 CI 随仓库膨胀线性变慢白白浪费 Nx 的核心能力不要忽视边界松懈的依赖约束会积累隐性技术债重构成本随项目规模指数上升不要过度拆分库库数量与复杂度要平衡粒度过细会导致维护与感知成本超过收益。小结从nx.json的输入指纹与任务编排到project.json的目标分层再到标签驱动的模块边界、组合式 generator、affected CI 与远程缓存这套模式构成了一条完整的 Nx 落地链路。对 Agent 与开发者而言references/details.md 是可随时复用的模板库SKILL.md 是导航与决策依据而 monorepo-architect Agent 则提供了从评估到落地的 8 步流程指引。三者配合即可在任意规模的项目中搭建出改动越小、验证越快、依赖越清晰的生产级 Nx 工作区。【免费下载链接】agentsMulti-harness agentic plugin marketplace for Claude Code, Codex, Cursor, OpenCode, GitHub Copilot, and Google Antigravity项目地址: https://gitcode.com/GitHub_Trending/agents24/agents创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
