Use Cases (更新: 2026/6/2)

Claude Code 与 Nx Workspace:Monorepo 入门实战

用 Claude Code 和 Nx Workspace 设计边界、查看 nx graph、配置 affected CI 与缓存,避免过度 monorepo。

Claude Code 与 Nx Workspace:Monorepo 入门实战

Nx Workspace 不是“大仓库”,而是边界地图

只对 Claude Code 说“帮我做一个 monorepo”,它通常能生成很多文件。但真正麻烦的是几周以后:apps/web 的改动会不会影响 apps/admin?按钮组件应该放在应用里,还是放进共享 UI?每个 PR 都要跑全部测试吗?

Nx Workspace 用 project graph、task graph、affected 命令和缓存来回答这些问题。官方 Nx mental model 解释了 Nx 如何分析项目并只运行必要任务。给初学者的说法是:Nx 是一张依赖地图加一个任务执行器,它先告诉你“谁依赖谁”,再帮你只验证需要验证的范围。

本文把 Claude Code 当作审查者和结对开发助手,而不是无约束的代码生成器。建议同时打开官方文档:create-nx-workspaceworkspace generatorsaffectedCI setupcaching tasks。相关背景可继续读 Claude Code monorepo 管理pnpm workspace 实战CI/CD 设置


什么时候值得用 Nx

Nx 很强,但不是每个小项目都需要。一个落地页加一个很小的 API,用普通仓库可能更快。Nx 适合边界和验证成本开始变高的场景。

第一个真实用例是多个应用共享类型或 UI。比如 apps/webapps/adminapps/apilibs/contractslibs/ui 放在一起,API 类型和 UI 基础组件可以在同一个 PR 里更新。

第二个用例是只跑受影响的 CI。内容站、课程页面、后台和 API 如果在同一个仓库里,每次都全量构建会越来越慢。nx affected -t test build 会根据 Git 差异和依赖图选择可能受影响的项目。

第三个用例是让 Claude Code 更安全。把 libs/ui 定义为纯 UI,libs/contracts 定义为 API 类型,libs/config 定义为共享工具配置,apps/* 定义为可部署应用,Claude Code 的改动范围就会收窄。对有广告、联盟链接、咨询表单或付费 CTA 的页面来说,这一点尤其重要。

如果你还说不清当前仓库的边界,先做一次 repo map first pass。Nx 会加速清晰的结构,但不会自动修好混乱的结构。


目标结构

本教程只做一个小型 workspace:两个 React 应用、一个 Node API、一个 UI 库、一个 contracts 库和一个 config 库。

flowchart LR
  web["apps/web\nReact + Vite"] --> ui["libs/ui\nUI primitives"]
  admin["apps/admin\nReact + Vite"] --> ui
  web --> contracts["libs/contracts\nAPI types"]
  admin --> contracts
  api["apps/api\nNode API"] --> contracts
  web --> config["libs/config\nlint/test config"]
  api --> config

规则很简单:apps/* 是运行和部署的单位,libs/* 是可复用的部件。库不能 import 应用。UI 库不应该读取 API 环境变量,contracts 库不应该包含 React 组件。

先把边界交给 Claude Code:

请先理解这个 Nx Workspace,不要急着改代码。

规则:
- apps/web 和 apps/admin 是前端应用
- apps/api 是 API
- libs/ui 只放展示型 UI 基础组件
- libs/contracts 放 API 类型和 Zod schema
- libs/config 放共享 ESLint、Vitest、TypeScript 配置
- libs/* 不能 import apps/*

改动前请查看 nx graph。改动后请给出 nx affected 验证命令。

可复制的初始化命令

以下命令假设已经安装 Node.js 20+、Git 和 pnpm。为了可复现,命令不依赖交互式问题。

npx create-nx-workspace@latest acme-nx \
  --workspaceType=integrated \
  --preset=apps \
  --packageManager=pnpm \
  --nxCloud=skip \
  --interactive=false

cd acme-nx
pnpm nx add @nx/react
pnpm nx add @nx/node

使用 Nx generator 创建项目。generator 会同步更新 Nx 配置、TypeScript path 和项目元数据,比手工建目录更稳定。

pnpm nx g @nx/react:app web \
  --directory=apps/web \
  --bundler=vite \
  --unitTestRunner=vitest \
  --e2eTestRunner=playwright \
  --style=css

pnpm nx g @nx/react:app admin \
  --directory=apps/admin \
  --bundler=vite \
  --unitTestRunner=vitest \
  --e2eTestRunner=none \
  --style=css

pnpm nx g @nx/node:app api \
  --directory=apps/api \
  --unitTestRunner=vitest

pnpm nx g @nx/react:lib ui \
  --directory=libs/ui \
  --unitTestRunner=vitest

pnpm nx g @nx/js:lib contracts \
  --directory=libs/contracts \
  --unitTestRunner=vitest

pnpm nx g @nx/js:lib config \
  --directory=libs/config \
  --unitTestRunner=none

生成后先看图:

pnpm nx graph
pnpm nx show projects
pnpm nx show project web

如果图里的线已经很多,先简化边界,不要继续增加库。


先读 project.json

对初学者来说,project.json 就是“这个项目能运行哪些任务”的清单。

{
  "name": "web",
  "sourceRoot": "apps/web/src",
  "projectType": "application",
  "targets": {
    "build": {
      "executor": "@nx/vite:build",
      "outputs": ["{options.outputPath}"],
      "options": {
        "outputPath": "dist/apps/web"
      }
    },
    "test": {
      "executor": "@nx/vite:test",
      "outputs": ["{workspaceRoot}/coverage/apps/web"],
      "options": {
        "passWithNoTests": true
      }
    },
    "serve": {
      "executor": "@nx/vite:dev-server",
      "options": {
        "buildTarget": "web:build"
      }
    }
  },
  "tags": ["scope:app", "type:web"]
}

让 Claude Code 先解释再修改:

请读取 apps/web/project.json,用初学者能懂的方式解释 build、test、serve。
如果需要改动,只提出最小 diff。
不要破坏 outputs、cache 行为和 dependsOn 关系。

outputs 很重要,因为 Nx 用它判断哪些产物可以缓存。路径写错会导致缓存失效,甚至复用旧产物。


把 affected 放进 CI

affected 是 Nx 最实用的部分。它会比较 Git 差异和依赖图,只对可能受影响的项目执行任务。

pnpm nx affected -t lint test build --base=main --head=HEAD
pnpm nx affected:graph --base=main --head=HEAD

GitHub Actions 里要拉完整历史,否则分支比较容易失败。CI 也要通过 nx 运行任务,直接调用 vitesteslinttsc 会绕过 Nx 的缓存和 affected 逻辑。

name: nx-ci

on:
  pull_request:
  push:
    branches: [main]

jobs:
  affected:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - uses: pnpm/action-setup@v4
        with:
          version: 10
      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: pnpm
      - run: pnpm install --frozen-lockfile
      - run: pnpm nx affected -t lint test build --base=origin/main --head=HEAD --parallel=3

团队规模变大后可以考虑 Nx Cloud 远程缓存。初学阶段建议先用本地缓存和 affected 证明价值,再决定是否增加远程缓存。


常见失败

第一,创建 libs/shared 后什么都往里放。让 Claude Code 先说明代码属于 UI、contracts、config 还是纯工具函数,再移动。

第二,libs/* import apps/*。这会让依赖方向反过来,库不再可复用。

第三,CI 里直接跑原始工具。优先使用 pnpm nx run-many -t testpnpm nx affected -t test

第四,第一周就过度设计。没有真实重复之前,不要急着创建一堆 libs/authlibs/domainlibs/data-access

第五,不看 graph 就让 Claude Code 修改。把“改动前 pnpm nx graph,改动后 pnpm nx affected -t test build”写进提示词。


变现角度:保护会赚钱的页面

像 ClaudeCodeLab 这样的站点,文章、培训页、后台、咨询表单和 analytics 可能在同一个仓库里。Nx 的价值不只是快,而是能说明收入相关页面是否被影响。libs/cta 改了,graph 能告诉 reviewer 哪些页面需要确认;libs/analytics 改了,affected CI 能提示哪些应用需要冒烟测试。

这对 AdSense 布局、联盟链接、结账 CTA 和咨询表单都很有用。团队想标准化 Claude Code 和 monorepo 工作流,可以查看 ClaudeCodeLab training。个人练习时,先运行本文命令并保存一张 nx graph 截图,再继续增加 package。

实际验证结果

我以 Masa 的方式验证时,先只创建 webadminapiuicontracts。修改 libs/contracts 的一个类型后,pnpm nx affected -t test build --base=main --head=HEAD 只选择依赖 contracts 的应用。只修改 libs/ui 时,API build 没有进入范围。关键不是背 Nx 参数,而是先让边界和 graph 可见,再让 Claude Code 写代码,改动就更容易审查。

总结

Nx Workspace 不是为了把仓库变大,而是为了让依赖可见、只验证受影响的项目,并给 Claude Code 明确边界。

从小结构开始,读懂 project.json,查看 nx graph,把 nx affected 放进 CI。做到这里,Claude Code 就不只是生成文件,而是能帮助维护 monorepo 结构。

#Claude Code #Nx #monorepo #workspace #构建工具
免费

免费 PDF: Claude Code 速查表

输入邮箱即可获取一页 PDF,整理常用命令、审查习惯和安全工作流。

我们会妥善保护你的信息,不发送垃圾邮件。

把 Claude Code 变成真正能带来结果的工作流

先领取中文说明的免费 PDF,再进入英文商品页选择合适的教材。如果你需要团队落地、流程设计或内容变现支持,也可以直接咨询。

Masa

关于作者

Masa

专注 Claude Code 实务流程、团队导入和内容转化的工程师。