Appearance
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 适用场景
- 大型企业应用:多个应用和库的复杂项目
- 全栈开发:前端、后端、移动端在同一仓库
- 微前端架构:多个独立前端应用
- 组件库开发:管理组件包和文档
- 多团队协作:不同团队维护不同应用
2. 安装与初始化
2.1 全局安装
bash
# 使用 npm
npm install -g nx
# 使用 pnpm
pnpm add -g nx
# 使用 yarn
yarn global add nx
# 验证安装
nx --version2.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
No2.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
└── .gitignore2.4 添加到现有项目
bash
# 在现有项目中添加 Nx
cd existing-project
npx nx@latest init
# 或使用 pnpm
pnpm dlx nx@latest init3. 核心概念
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=none3.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-app3.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-generator3.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-app4.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=app34.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~14.4 依赖图
bash
# 查看项目依赖图
nx graph
# 查看受影响项目的依赖图
nx affected:graph
# 生成 HTML 文件
nx graph --file=graph.html
# 查看特定项目的依赖
nx graph --focus=my-app4.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=105. 智能缓存
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=build5.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:shared6.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-hooksNext.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-appNode.js 插件
bash
# 安装
npm install -D @nx/node
# 创建应用
nx g @nx/node:app api
# 创建库
nx g @nx/node:lib databaseExpress 插件
bash
# 安装
npm install -D @nx/express
# 创建应用
nx g @nx/express:app api
# 创建中间件
nx g @nx/express:middleware auth --project=api7.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/jest7.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-plugintypescript
// 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-plugintypescript
// 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 publish9. 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-agents9.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/web10. 性能优化
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=HEAD10.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 --buildablejson
// 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-lib11. 最佳实践
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-generatorstypescript
// 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=html11.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 --serve12. 常见问题与解决方案
12.1 缓存问题
问题: 缓存导致构建结果不正确
解决方案:
bash
# 清除本地缓存
nx reset
# 清除并重新安装
rm -rf node_modules .nx
npm install
# 跳过缓存
nx build my-app --skip-nx-cache12.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 核心优势
- 智能构建系统:只构建受影响的项目,大幅提升效率
- 强大的缓存机制:本地和远程缓存,避免重复计算
- 完善的工具链:代码生成、测试、部署一应俱全
- 严格的架构管理:模块边界规则,保持代码质量
- 丰富的插件生态:支持各种框架和工具
13.2 适用场景
- 大型企业级应用
- Monorepo 项目管理
- 微前端架构
- 组件库开发
- 全栈项目
13.3 关键要点
- 合理使用标签和边界规则
- 充分利用缓存机制
- 使用生成器标准化代码
- 基于受影响项目的构建和测试
- 集成 Nx Cloud 提升 CI 性能
通过合理使用 Nx 工具链,可以极大提升大型项目的开发效率和代码质量,是企业级 Monorepo 的最佳选择之一。