Skip to content

Nx 工具链 - 企业级 Monorepo 解决方案

1. Nx 简介

1.1 什么是 Nx

Nx 是一个强大的开源构建系统和 Monorepo 工具链,由 Nrwl 团队开发。它提供了智能构建、测试和开发工具,专为大型企业级项目设计。

核心特性:

  • 智能构建系统:只构建受影响的项目
  • 强大的依赖图:可视化项目依赖关系
  • 代码生成器:标准化的项目和代码生成
  • 插件系统:丰富的官方和社区插件
  • 缓存机制:本地和远程计算缓存
  • 任务编排:并行执行任务,优化性能

1.2 为什么选择 Nx

与其他工具对比

Nx vs Lerna

bash
# Lerna 特点
- 轻量级,专注于版本管理
- 功能相对简单
- 缺少智能构建能力
- 维护相对不活跃

# Nx 特点
- 功能全面,企业级
- 智能的增量构建
- 强大的插件生态
- 持续活跃的维护

Nx vs Turborepo

bash
# Turborepo 特点
- 专注于构建性能
- 配置简单
- 功能相对单一
- 主要关注缓存

# Nx 特点
- 功能更全面
- 代码生成和项目管理
- 更强大的依赖分析
- 丰富的开发工具

1.3 适用场景

  1. 大型企业应用:多个应用和库的复杂项目
  2. 全栈开发:前端、后端、移动端在同一仓库
  3. 微前端架构:多个独立前端应用
  4. 组件库开发:管理组件包和文档
  5. 多团队协作:不同团队维护不同应用

2. 安装与初始化

2.1 全局安装

bash
# 使用 npm
npm install -g nx

# 使用 pnpm
pnpm add -g nx

# 使用 yarn
yarn global add nx

# 验证安装
nx --version

2.2 创建新工作空间

使用 create-nx-workspace

bash
# 创建新工作空间
npx create-nx-workspace@latest

# 或使用 pnpm
pnpm create nx-workspace

# 或使用 yarn
yarn create nx-workspace

配置选项

bash
? Workspace name (e.g., org name)     my-org
? What to create in the new workspace 
 apps              [an empty workspace with a layout that works best for building apps]
    react             [a workspace with a single React application]
    angular           [a workspace with a single Angular application]
    next.js           [a workspace with a single Next.js application]
    express           [a workspace with a single Express application]
    react-native      [a workspace with a single React Native application]
    
? Which bundler would you like to use?
 webpack           [Webpack is a popular bundler]
    vite              [Vite is a modern bundler]
    rspack            [Rspack is a fast Rust-based bundler]
    
? Test runner to use for end to end (E2E) tests
 cypress           [Cypress is a modern E2E testing tool]
    playwright        [Playwright is a modern E2E testing tool]
    none              [Skip E2E test runner]
    
? Default stylesheet format
 CSS
    SCSS
    Less
    styled-components
    emotion
    
? Enable distributed caching to make your CI faster
 Yes
    No

2.3 工作空间结构

创建后的工作空间结构:

my-org/
├── apps/                    # 应用目录
│   ├── my-app/
│   │   ├── src/
│   │   ├── project.json    # 项目配置
│   │   └── tsconfig.json
│   └── my-app-e2e/         # E2E 测试
│       ├── src/
│       └── project.json
├── libs/                    # 库目录
├── tools/                   # 自定义工具
├── nx.json                  # Nx 配置
├── tsconfig.base.json       # TypeScript 基础配置
├── package.json
└── .gitignore

2.4 添加到现有项目

bash
# 在现有项目中添加 Nx
cd existing-project
npx nx@latest init

# 或使用 pnpm
pnpm dlx nx@latest init

3. 核心概念

3.1 项目(Projects)

项目是 Nx 工作空间的基本单元,可以是应用(app)或库(lib)。

应用(Apps)

bash
# 创建 React 应用
nx g @nx/react:app my-app

# 创建 Next.js 应用
nx g @nx/next:app my-next-app

# 创建 Express 应用
nx g @nx/express:app api

# 创建 React Native 应用
nx g @nx/react-native:app mobile

库(Libs)

bash
# 创建 React 库
nx g @nx/react:lib ui-components

# 创建工具库
nx g @nx/js:lib utils

# 创建类型库
nx g @nx/js:lib types --bundler=none

3.2 项目配置(project.json)

每个项目都有 project.json 配置文件:

json
{
  "$schema": "../../node_modules/nx/schemas/project-schema.json",
  "name": "my-app",
  "projectType": "application",
  "sourceRoot": "apps/my-app/src",
  "targets": {
    "build": {
      "executor": "@nx/webpack:webpack",
      "outputs": ["{options.outputPath}"],
      "options": {
        "outputPath": "dist/apps/my-app",
        "index": "apps/my-app/src/index.html",
        "main": "apps/my-app/src/main.tsx",
        "polyfills": "apps/my-app/src/polyfills.ts",
        "tsConfig": "apps/my-app/tsconfig.app.json",
        "assets": [
          "apps/my-app/src/favicon.ico",
          "apps/my-app/src/assets"
        ],
        "styles": ["apps/my-app/src/styles.css"],
        "scripts": []
      },
      "configurations": {
        "production": {
          "optimization": true,
          "extractLicenses": true,
          "sourceMap": false
        }
      }
    },
    "serve": {
      "executor": "@nx/webpack:dev-server",
      "options": {
        "buildTarget": "my-app:build",
        "port": 4200
      },
      "configurations": {
        "production": {
          "buildTarget": "my-app:build:production"
        }
      }
    },
    "test": {
      "executor": "@nx/jest:jest",
      "outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
      "options": {
        "jestConfig": "apps/my-app/jest.config.ts",
        "passWithNoTests": true
      }
    }
  },
  "tags": ["type:app", "scope:client"]
}

3.3 执行器(Executors)

执行器是执行特定任务的工具:

bash
# 运行构建执行器
nx build my-app

# 运行测试执行器
nx test my-app

# 运行自定义执行器
nx custom-task my-app

3.4 生成器(Generators)

生成器用于创建或修改代码:

bash
# 生成组件
nx g @nx/react:component Button --project=ui-components

# 生成库
nx g @nx/js:lib feature-auth

# 生成服务
nx g @nx/node:service user --project=api

# 自定义生成器
nx g @my-org/plugin:custom-generator

3.5 标签(Tags)

标签用于组织和限制项目依赖关系:

json
// project.json
{
  "tags": ["type:app", "scope:admin", "platform:web"]
}

配置依赖约束:

json
// nx.json
{
  "targetDefaults": {
    "build": {
      "dependsOn": ["^build"]
    }
  },
  "namedInputs": {
    "default": ["{projectRoot}/**/*"],
    "production": ["!{projectRoot}/**/*.spec.ts"]
  },
  "extends": "nx/presets/npm.json"
}

4. 任务执行

4.1 基本命令

bash
# 运行目标任务
nx [target] [project]

# 示例
nx build my-app
nx test ui-components
nx lint api
nx serve my-app

4.2 运行多个项目

bash
# 运行所有项目的构建
nx run-many --target=build --all

# 运行特定项目
nx run-many --target=build --projects=app1,app2,lib1

# 使用标签过滤
nx run-many --target=test --tags=scope:admin

# 排除特定项目
nx run-many --target=build --all --exclude=app3

4.3 受影响的项目

bash
# 只构建受影响的项目
nx affected:build

# 只测试受影响的项目
nx affected:test

# 运行所有受影响项目的任务
nx affected --target=build

# 基于特定基准
nx affected:build --base=main --head=HEAD

# 指定基准提交
nx affected:build --base=origin/main~1

4.4 依赖图

bash
# 查看项目依赖图
nx graph

# 查看受影响项目的依赖图
nx affected:graph

# 生成 HTML 文件
nx graph --file=graph.html

# 查看特定项目的依赖
nx graph --focus=my-app

4.5 并行执行

bash
# 并行运行(默认 3 个并发)
nx run-many --target=build --all --parallel

# 指定并发数
nx run-many --target=build --all --parallel=5

# 最大并发
nx run-many --target=build --all --maxParallel=10

5. 智能缓存

5.1 本地缓存

Nx 会自动缓存任务结果:

json
// nx.json
{
  "tasksRunnerOptions": {
    "default": {
      "runner": "nx/tasks-runners/default",
      "options": {
        "cacheableOperations": ["build", "test", "lint"]
      }
    }
  }
}

5.2 缓存目录

bash
# 缓存位置
node_modules/.cache/nx

# 清除缓存
nx reset

# 查看缓存统计
nx show projects --with-target=build

5.3 计算哈希

Nx 基于以下内容计算缓存键:

  • 源代码文件
  • 依赖项的锁定文件
  • 命令参数
  • 环境变量
  • 运行时值

配置输入:

json
// project.json
{
  "targets": {
    "build": {
      "inputs": [
        "default",
        "^production",
        {
          "env": "NODE_ENV"
        },
        {
          "runtime": "node -v"
        }
      ],
      "outputs": ["{options.outputPath}"]
    }
  }
}

5.4 Nx Cloud 远程缓存

设置 Nx Cloud

bash
# 连接到 Nx Cloud
nx connect-to-nx-cloud

# 手动配置
# nx.json
{
  "nxCloudAccessToken": "YOUR_ACCESS_TOKEN"
}

使用远程缓存

bash
# 自动使用远程缓存
nx build my-app

# 跳过远程缓存
nx build my-app --skip-nx-cache

# 查看缓存状态
nx show projects

分布式任务执行(DTE)

json
// nx.json
{
  "tasksRunnerOptions": {
    "default": {
      "runner": "@nrwl/nx-cloud",
      "options": {
        "accessToken": "YOUR_TOKEN",
        "cacheableOperations": ["build", "test", "lint"],
        "parallel": 3,
        "distributedTasksExecution": true
      }
    }
  }
}

6. 项目边界管理

6.1 模块边界规则

使用 ESLint 强制执行边界规则:

json
// .eslintrc.json
{
  "overrides": [
    {
      "files": ["*.ts", "*.tsx"],
      "extends": ["plugin:@nx/typescript"],
      "rules": {
        "@nx/enforce-module-boundaries": [
          "error",
          {
            "enforceBuildableLibDependency": true,
            "allow": [],
            "depConstraints": [
              {
                "sourceTag": "scope:admin",
                "onlyDependOnLibsWithTags": [
                  "scope:admin",
                  "scope:shared"
                ]
              },
              {
                "sourceTag": "scope:client",
                "onlyDependOnLibsWithTags": [
                  "scope:client",
                  "scope:shared"
                ]
              },
              {
                "sourceTag": "type:app",
                "onlyDependOnLibsWithTags": [
                  "type:feature",
                  "type:ui",
                  "type:util"
                ]
              },
              {
                "sourceTag": "type:feature",
                "onlyDependOnLibsWithTags": [
                  "type:ui",
                  "type:util",
                  "type:data-access"
                ]
              },
              {
                "sourceTag": "type:ui",
                "onlyDependOnLibsWithTags": ["type:util"]
              },
              {
                "sourceTag": "type:util",
                "onlyDependOnLibsWithTags": []
              }
            ]
          }
        ]
      }
    }
  ]
}

6.2 库类型分类

推荐的库类型:

bash
# Feature 库 - 业务功能
nx g @nx/react:lib feature-auth --directory=libs/admin/feature-auth --tags=type:feature,scope:admin

# UI 库 - UI 组件
nx g @nx/react:lib ui-buttons --directory=libs/shared/ui-buttons --tags=type:ui,scope:shared

# Data Access 库 - 数据访问
nx g @nx/js:lib data-access-api --directory=libs/shared/data-access-api --tags=type:data-access,scope:shared

# Util 库 - 工具函数
nx g @nx/js:lib util-formatting --directory=libs/shared/util-formatting --tags=type:util,scope:shared

6.3 项目结构最佳实践

libs/
├── admin/                  # 管理后台范围
│   ├── feature-dashboard/  # 功能库
│   ├── feature-users/
│   └── data-access-admin/  # 数据访问库
├── client/                 # 客户端范围
│   ├── feature-home/
│   ├── feature-products/
│   └── data-access-client/
└── shared/                 # 共享范围
    ├── ui-components/      # UI 库
    ├── ui-layout/
    ├── util-formatters/    # 工具库
    └── util-validators/

7. 插件系统

7.1 官方插件

React 插件

bash
# 安装
npm install -D @nx/react

# 创建应用
nx g @nx/react:app my-react-app

# 创建库
nx g @nx/react:lib ui-components

# 创建组件
nx g @nx/react:component Button --project=ui-components

# 创建 Hook
nx g @nx/react:hook useAuth --project=shared-hooks

Next.js 插件

bash
# 安装
npm install -D @nx/next

# 创建应用
nx g @nx/next:app my-next-app

# 创建页面
nx g @nx/next:page products --project=my-next-app

# 创建组件
nx g @nx/next:component Header --project=my-next-app

Node.js 插件

bash
# 安装
npm install -D @nx/node

# 创建应用
nx g @nx/node:app api

# 创建库
nx g @nx/node:lib database

Express 插件

bash
# 安装
npm install -D @nx/express

# 创建应用
nx g @nx/express:app api

# 创建中间件
nx g @nx/express:middleware auth --project=api

7.2 社区插件

bash
# Angular
npm install -D @nx/angular

# Vue
npm install -D @nx/vue

# Nest.js
npm install -D @nx/nest

# Storybook
npm install -D @nx/storybook

# Cypress
npm install -D @nx/cypress

# Jest
npm install -D @nx/jest

7.3 创建自定义插件

生成插件项目

bash
# 创建插件
nx g @nx/plugin:plugin my-plugin

# 项目结构
libs/my-plugin/
├── src/
   ├── generators/         # 生成器
   └── my-generator/
   ├── executors/          # 执行器
   └── my-executor/
   └── index.ts
├── generators.json         # 生成器配置
├── executors.json          # 执行器配置
└── package.json

创建生成器

bash
# 添加生成器
nx g @nx/plugin:generator my-generator --project=my-plugin
typescript
// libs/my-plugin/src/generators/my-generator/generator.ts
import { Tree, formatFiles, generateFiles } from '@nx/devkit';
import * as path from 'path';

export interface MyGeneratorSchema {
  name: string;
  directory?: string;
}

export default async function (tree: Tree, options: MyGeneratorSchema) {
  const projectRoot = options.directory
    ? `${options.directory}/${options.name}`
    : options.name;

  generateFiles(
    tree,
    path.join(__dirname, 'files'),
    projectRoot,
    options
  );

  await formatFiles(tree);
}

创建执行器

bash
# 添加执行器
nx g @nx/plugin:executor my-executor --project=my-plugin
typescript
// libs/my-plugin/src/executors/my-executor/executor.ts
import { ExecutorContext } from '@nx/devkit';

export interface MyExecutorOptions {
  option1: string;
  option2: number;
}

export default async function runExecutor(
  options: MyExecutorOptions,
  context: ExecutorContext
) {
  console.log('Executor ran for', context.projectName);
  console.log('Options:', options);

  return {
    success: true
  };
}

8. 实战案例

8.1 创建全栈应用

步骤 1:创建工作空间

bash
npx create-nx-workspace@latest my-fullstack-app --preset=apps
cd my-fullstack-app

步骤 2:添加前端应用

bash
# 安装 React 插件
npm install -D @nx/react

# 创建 React 应用
nx g @nx/react:app web --bundler=vite --e2eTestRunner=playwright

步骤 3:添加后端应用

bash
# 安装 Express 插件
npm install -D @nx/express

# 创建 Express 应用
nx g @nx/express:app api

步骤 4:创建共享库

bash
# 创建类型库
nx g @nx/js:lib shared-types --bundler=none

# 创建工具库
nx g @nx/js:lib shared-utils

步骤 5:定义共享类型

typescript
// libs/shared-types/src/lib/user.ts
export interface User {
  id: string;
  email: string;
  name: string;
  createdAt: Date;
}

export interface CreateUserDto {
  email: string;
  name: string;
  password: string;
}

步骤 6:实现后端 API

typescript
// apps/api/src/app/routes/users.ts
import express from 'express';
import { User, CreateUserDto } from '@my-fullstack-app/shared-types';

const router = express.Router();

router.post('/users', async (req, res) => {
  const dto: CreateUserDto = req.body;
  
  const user: User = {
    id: Math.random().toString(36),
    email: dto.email,
    name: dto.name,
    createdAt: new Date()
  };
  
  res.json(user);
});

export default router;

步骤 7:实现前端

tsx
// apps/web/src/app/app.tsx
import { User, CreateUserDto } from '@my-fullstack-app/shared-types';

export function App() {
  const createUser = async (dto: CreateUserDto) => {
    const response = await fetch('http://localhost:3000/api/users', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(dto)
    });
    
    const user: User = await response.json();
    return user;
  };

  return <div>My App</div>;
}

8.2 微前端架构

使用 Module Federation

bash
# 安装插件
npm install -D @nx/react

# 创建宿主应用
nx g @nx/react:host shell --remotes=admin,dashboard

# 项目结构
apps/
├── shell/              # 宿主应用
├── admin/              # 远程应用 1
└── dashboard/          # 远程应用 2

配置 Module Federation

javascript
// apps/shell/module-federation.config.js
module.exports = {
  name: 'shell',
  remotes: [
    'admin',
    'dashboard'
  ]
};
javascript
// apps/admin/module-federation.config.js
module.exports = {
  name: 'admin',
  exposes: {
    './Module': './src/remote-entry.ts'
  }
};

在宿主应用中加载远程模块

tsx
// apps/shell/src/app/app.tsx
import * as React from 'react';
import { Link, Route, Routes } from 'react-router-dom';

const Admin = React.lazy(() => import('admin/Module'));
const Dashboard = React.lazy(() => import('dashboard/Module'));

export function App() {
  return (
    <React.Suspense fallback={<div>Loading...</div>}>
      <Routes>
        <Route path="/admin" element={<Admin />} />
        <Route path="/dashboard" element={<Dashboard />} />
      </Routes>
    </React.Suspense>
  );
}

8.3 组件库开发

步骤 1:创建组件库

bash
# 创建 React 库
nx g @nx/react:lib ui --publishable --importPath=@myorg/ui

# 项目结构
libs/ui/
├── src/
   ├── lib/
   └── ui.tsx
   └── index.ts
├── project.json
├── tsconfig.json
└── package.json

步骤 2:添加组件

bash
# 生成 Button 组件
nx g @nx/react:component Button --project=ui --export

# 生成 Input 组件
nx g @nx/react:component Input --project=ui --export

步骤 3:配置构建

json
// libs/ui/project.json
{
  "targets": {
    "build": {
      "executor": "@nx/rollup:rollup",
      "outputs": ["{options.outputPath}"],
      "options": {
        "outputPath": "dist/libs/ui",
        "tsConfig": "libs/ui/tsconfig.lib.json",
        "project": "libs/ui/package.json",
        "entryFile": "libs/ui/src/index.ts",
        "external": ["react", "react-dom"],
        "rollupConfig": "@nx/react/plugins/bundle-rollup",
        "compiler": "babel",
        "format": ["esm", "cjs"]
      }
    }
  }
}

步骤 4:添加 Storybook

bash
# 安装 Storybook 插件
npm install -D @nx/storybook

# 配置 Storybook
nx g @nx/react:storybook-configuration ui

# 运行 Storybook
nx storybook ui

步骤 5:创建 Stories

tsx
// libs/ui/src/lib/Button.stories.tsx
import type { Meta, StoryObj } from '@storybook/react';
import { Button } from './Button';

const meta: Meta<typeof Button> = {
  component: Button,
  title: 'UI/Button',
};

export default meta;
type Story = StoryObj<typeof Button>;

export const Primary: Story = {
  args: {
    children: 'Primary Button',
    variant: 'primary',
  },
};

export const Secondary: Story = {
  args: {
    children: 'Secondary Button',
    variant: 'secondary',
  },
};

步骤 6:发布组件库

bash
# 构建
nx build ui

# 发布到 npm
cd dist/libs/ui
npm publish

9. CI/CD 集成

9.1 GitHub Actions

基本 CI 配置

yaml
# .github/workflows/ci.yml
name: CI

on:
  push:
    branches:
      - main
  pull_request:

jobs:
  main:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
        with:
          fetch-depth: 0
      
      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: 18
          cache: 'npm'
      
      - name: Install dependencies
        run: npm ci
      
      - name: Derive appropriate SHAs for base and head
        uses: nrwl/nx-set-shas@v3
      
      - name: Run affected commands
        run: |
          npx nx affected --target=lint --parallel=3
          npx nx affected --target=test --parallel=3 --ci --code-coverage
          npx nx affected --target=build --parallel=3

使用 Nx Cloud

yaml
# .github/workflows/ci.yml
name: CI

on: [push]

jobs:
  main:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
        with:
          fetch-depth: 0
      
      - uses: actions/setup-node@v3
        with:
          node-version: 18
      
      - run: npm ci
      
      - uses: nrwl/nx-set-shas@v3
      
      - name: Start Nx Agents
        run: npx nx-cloud start-ci-run --distribute-on="3 linux-medium-js"
      
      - name: Run affected commands
        run: |
          npx nx affected --target=build --parallel=3
          npx nx affected --target=test --parallel=3
      
      - name: Stop Nx Agents
        if: always()
        run: npx nx-cloud stop-all-agents

9.2 GitLab CI

yaml
# .gitlab-ci.yml
image: node:18

stages:
  - install
  - test
  - build

cache:
  paths:
    - node_modules/
    - .nx/cache

install:
  stage: install
  script:
    - npm ci
  artifacts:
    paths:
      - node_modules/

affected:test:
  stage: test
  script:
    - npx nx affected --target=test --base=origin/main --head=HEAD --parallel=3

affected:build:
  stage: build
  script:
    - npx nx affected --target=build --base=origin/main --head=HEAD --parallel=3
  artifacts:
    paths:
      - dist/

9.3 部署配置

yaml
# .github/workflows/deploy.yml
name: Deploy

on:
  push:
    branches:
      - main

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - uses: actions/setup-node@v3
        with:
          node-version: 18
      
      - run: npm ci
      
      - name: Build
        run: npx nx build web --configuration=production
      
      - name: Deploy to Vercel
        uses: amondnet/vercel-action@v20
        with:
          vercel-token: ${{ secrets.VERCEL_TOKEN }}
          vercel-org-id: ${{ secrets.ORG_ID }}
          vercel-project-id: ${{ secrets.PROJECT_ID }}
          working-directory: ./dist/apps/web

10. 性能优化

10.1 优化构建时间

使用缓存

json
// nx.json
{
  "tasksRunnerOptions": {
    "default": {
      "runner": "nx/tasks-runners/default",
      "options": {
        "cacheableOperations": ["build", "test", "lint", "e2e"]
      }
    }
  }
}

并行执行

bash
# 最大并行数
nx run-many --target=build --all --parallel=5

# 根据 CPU 核心数
nx run-many --target=build --all --maxParallel=$(nproc)

只构建受影响的项目

bash
# 本地开发
nx affected:build

# CI 中
nx affected:build --base=origin/main --head=HEAD

10.2 优化依赖图

避免循环依赖

bash
# 检测循环依赖
nx graph --file=graph.html

# 使用 lint 规则检测
# .eslintrc.json
{
  "rules": {
    "@nx/enforce-module-boundaries": [
      "error",
      {
        "allow": [],
        "depConstraints": [...]
      }
    ]
  }
}

减少不必要的依赖

typescript
// 不好的做法 - 导入整个库
import _ from 'lodash';

// 好的做法 - 只导入需要的函数
import debounce from 'lodash/debounce';

10.3 优化项目结构

使用 buildable 库

bash
# 创建可构建的库
nx g @nx/react:lib my-lib --buildable
json
// libs/my-lib/project.json
{
  "targets": {
    "build": {
      "executor": "@nx/js:tsc",
      "outputs": ["{options.outputPath}"],
      "options": {
        "outputPath": "dist/libs/my-lib",
        "main": "libs/my-lib/src/index.ts",
        "tsConfig": "libs/my-lib/tsconfig.lib.json"
      }
    }
  }
}

使用 publishable 库

bash
# 创建可发布的库
nx g @nx/react:lib my-lib --publishable --importPath=@myorg/my-lib

11. 最佳实践

11.1 项目组织

按领域组织

libs/
├── users/
│   ├── feature-profile/
│   ├── feature-settings/
│   ├── data-access/
│   └── ui/
├── products/
│   ├── feature-list/
│   ├── feature-detail/
│   ├── data-access/
│   └── ui/
└── shared/
    ├── ui/
    └── utils/

按类型组织

libs/
├── feature/
│   ├── user-profile/
│   ├── user-settings/
│   └── product-list/
├── ui/
│   ├── buttons/
│   ├── forms/
│   └── layout/
├── data-access/
│   ├── user-api/
│   └── product-api/
└── utils/
    ├── formatters/
    └── validators/

11.2 命名约定

bash
# 应用命名
apps/web-admin
apps/mobile-client
apps/api-gateway

# 库命名(带 scope 和 type)
libs/admin/feature-dashboard
libs/admin/ui-components
libs/shared/data-access-api
libs/shared/util-formatting

# 标签使用
tags: ["scope:admin", "type:feature"]
tags: ["scope:shared", "type:ui"]

11.3 代码生成标准化

创建自定义生成器模板:

bash
# 生成自定义生成器
nx g @nx/plugin:plugin tools-generators

# 创建 feature 生成器
nx g @nx/plugin:generator feature --project=tools-generators
typescript
// libs/tools-generators/src/generators/feature/generator.ts
export default async function (tree: Tree, options: FeatureGeneratorSchema) {
  const { name, directory, scope } = options;
  
  // 生成 feature 库
  await libraryGenerator(tree, {
    name: `feature-${name}`,
    directory: `${directory}/${scope}/feature-${name}`,
    tags: `scope:${scope},type:feature`,
    buildable: true
  });
  
  // 生成标准组件结构
  // ...
  
  await formatFiles(tree);
}

11.4 测试策略

bash
# 单元测试
nx test my-lib

# E2E 测试
nx e2e my-app-e2e

# 集成测试
nx test my-app --testPathPattern=integration

# 覆盖率报告
nx test my-lib --coverage --coverageReporters=html

11.5 文档管理

bash
# 生成项目文档
nx graph --file=docs/architecture.html

# 使用 Compodoc 生成 API 文档
npm install -D @compodoc/compodoc
nx g @nx/angular:setup-compodoc my-app

# 运行文档服务
nx compodoc my-app --serve

12. 常见问题与解决方案

12.1 缓存问题

问题: 缓存导致构建结果不正确

解决方案:

bash
# 清除本地缓存
nx reset

# 清除并重新安装
rm -rf node_modules .nx
npm install

# 跳过缓存
nx build my-app --skip-nx-cache

12.2 依赖图错误

问题: 依赖图显示不正确的依赖关系

解决方案:

bash
# 重新生成依赖图
nx reset
nx graph

# 检查 tsconfig 路径映射
# tsconfig.base.json
{
  "compilerOptions": {
    "paths": {
      "@myorg/my-lib": ["libs/my-lib/src/index.ts"]
    }
  }
}

12.3 模块解析问题

问题: TypeScript 无法解析模块

解决方案:

json
// tsconfig.base.json
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@myorg/*": ["libs/*/src"]
    }
  }
}

12.4 Executor 失败

问题: 自定义 executor 执行失败

解决方案:

typescript
// 添加详细日志
export default async function runExecutor(
  options: MyExecutorOptions,
  context: ExecutorContext
) {
  console.log('Context:', JSON.stringify(context, null, 2));
  console.log('Options:', JSON.stringify(options, null, 2));
  
  try {
    // 执行逻辑
    return { success: true };
  } catch (error) {
    console.error('Error:', error);
    return { success: false };
  }
}

13. 总结

13.1 核心优势

  1. 智能构建系统:只构建受影响的项目,大幅提升效率
  2. 强大的缓存机制:本地和远程缓存,避免重复计算
  3. 完善的工具链:代码生成、测试、部署一应俱全
  4. 严格的架构管理:模块边界规则,保持代码质量
  5. 丰富的插件生态:支持各种框架和工具

13.2 适用场景

  • 大型企业级应用
  • Monorepo 项目管理
  • 微前端架构
  • 组件库开发
  • 全栈项目

13.3 关键要点

  1. 合理使用标签和边界规则
  2. 充分利用缓存机制
  3. 使用生成器标准化代码
  4. 基于受影响项目的构建和测试
  5. 集成 Nx Cloud 提升 CI 性能

通过合理使用 Nx 工具链,可以极大提升大型项目的开发效率和代码质量,是企业级 Monorepo 的最佳选择之一。