从零开始玩转 nx:新手也能轻松上手的 Monorepo 实战指南
你有没有遇到过这样的场景?
团队里三个前端项目,长得几乎一模一样——同样的按钮组件、一样的工具函数、甚至连 ESLint 配置都复制粘贴了三遍。结果改一个颜色变量,要手动同步到四个仓库;修复一个类型错误,得提交三次 PR。更别提 CI 流水线每次都要从头构建所有项目,等十分钟才能看到测试结果。
这还只是开始。当业务复杂起来,微前端拆分、共享库维护、多端协同开发……整个工程体系就像一辆越来越难驾驭的重型卡车,每加一个功能,方向盘就更沉一分。
而 nx,就是那辆能让你把这辆卡车变成磁悬浮列车的引擎。
为什么是 nx?前端工程化的“操作系统”来了
在讲怎么用之前,我们先聊聊:到底什么是 nx?
你可以把它理解为现代前端项目的“智能操作系统”。它不像 create-react-app 只管初始化一个应用,也不像 webpack 只负责打包——nx 管的是整个代码宇宙的运行逻辑。
它的核心身份是一个Monorepo 工具。所谓 Monorepo(单体仓库),就是一个 Git 仓库里放多个项目。比如:
- 主站 Web 应用
- 管理后台
- 移动端 React Native 项目
- 共享 UI 组件库
- 数据请求层封装
- Node.js 后端服务
这些统统放在一个仓库里,由 nx 统一调度。听起来有点“重”?但正是这种结构,解决了大型项目中最让人头疼的问题:依赖混乱、重复构建、协作低效。
nx 到底强在哪?
举个最直观的例子:
假设你修改了一个叫shared-utils的公共函数库。传统流程怎么做?
→ 拉取所有项目 → 全量安装依赖 → 全部重新 build → 跑所有测试 → 等一小时……
而在 nx 中,只需要一条命令:
nx affected:testnx 会自动分析出:“哦,只有admin-web和mobile-app引用了这个库”,于是只给这两个项目跑测试,其他项目直接跳过。节省的时间不是一点点,而是成倍地减少。
这就是 nx 的杀手锏:基于依赖图的智能影响分析 + 增量构建。
安装与初始化:三分钟搭建你的第一个 nx 工作区
准备环境
确保你本地有:
- Node.js ≥ v16.14(推荐 v18+)
- npm / yarn / pnpm 任选其一
- Git(用于变更追踪)
如果你经常切换 Node 版本,强烈建议使用 nvm 来管理。
创建工作区
nx 提供了一个超友好的脚手架命令:
npx create-nx-workspace@latest myorg执行后会进入交互式引导,关键几步如下:
- 选择模板类型:
-empty:空项目,适合自定义架构
-react/angular/vue:预配置对应框架
-nest/express:后端服务模板
新手建议选
react或empty,本文以empty为例。
- 命名工作区(比如
myorg) - 是否启用分布式缓存(CI 加速用,可先跳过)
等待安装完成后,你会看到一个清爽的目录结构:
myorg/ ├── apps/ # 所有应用入口 ├── libs/ # 可复用库 ├── tools/ # 自定义脚本 ├── nx.json # nx 核心配置 ├── package.json ├── tsconfig.base.json # 全局 TS 配置 └── project.json # 单个项目任务定义(取代旧 workspace.json)是不是很整洁?每个部分各司其职,没有多余的文件污染根目录。
日常开发五件套:掌握这五个命令,你就能干活了
别被文档里的几十个命令吓到,实际开发中,90% 的操作靠下面这五个就够了。
1. 生成新项目:告别手动创建文件夹
想加一个新页面应用?或者建个通用组件库?不用自己 mkdir 了。
# 创建一个 React 应用 nx generate @nrwl/react:application --name=dashboard --style=scss --bundler=vite这条命令干了什么?
- 在apps/dashboard下生成完整 React 项目
- 自动配置 Vite 构建
- 支持 SCSS 样式
- 注册进 nx 项目列表,后续可用nx serve dashboard启动
再比如,创建一个共享 UI 库:
nx generate @nrwl/react:library \ --name=ui \ --directory=shared \ --style=css \ --unitTestRunner=jest生成路径将是libs/shared/ui,并且自动加上 Jest 测试支持。
💡 小技巧:可以用
nx g简写代替nx generate
2. 启动开发服务器:热更新全都有
启动刚才创建的 dashboard:
nx serve dashboard等价于:
nx run dashboard:servenx 会根据project.json中的配置,拉起 Vite 或 Webpack Dev Server,默认监听localhost:4200,并开启 HMR(热模块替换),改代码即时刷新,体验丝滑。
如果想指定端口,在project.json里改:
"serve": { "executor": "@nrwl/vite:dev-server", "options": { "buildTarget": "dashboard:build", "port": 3000 } }3. 构建生产包:精准编译不浪费
发布前构建:
nx build dashboardnx 会:
- 先检查dashboard是否依赖任何 lib(如shared/ui)
- 若依赖项未构建或已变更,则自动先构建它们
- 最终输出至dist/apps/dashboard
而且!如果你之前已经构建过一次,这次只改了一行 JS,nx 会利用缓存机制直接复用上次结果,跳过整个编译过程,速度飞起。
4. 运行测试和 Lint:质量守门员
单元测试:
nx test dashboard支持--watch模式实时反馈:
nx test dashboard --watch代码规范检查:
nx lint dashboard同样支持增量执行:只有改动过的文件才会被 lint,再也不用等十几秒看一堆无关警告。
5. 查看依赖图:一眼看穿项目关系
这是 nx 最酷的功能之一:
nx graph执行后浏览器自动打开一张可视化图表,展示当前所有项目之间的引用关系:
- 哪些 app 用了哪个 lib
- 哪些库之间存在依赖
- 是否有循环依赖(红色警示)
还能过滤查看“受影响的项目”:
nx graph --affected提交代码前跑一下,立刻知道这次改动会影响哪些模块,心里有底多了。
📌 提示:可以用
nx graph --file=dep-graph.html导出静态图,嵌入 Wiki 文档。
高阶玩法:让 nx 为你打工
影响分析:CI 流水线提速神器
当你在 Git 分支上修改了一个 shared 库,如何知道该重新测试哪些项目?
答案还是那个神奇的命令:
nx affected:apps输出可能是:
✔ Found 2 affected apps - dashboard - admin-panel接着就可以精准打击:
nx affected:test # 只跑受影响项目的测试 nx affected:build # 只构建受影响的应用在 CI 中加入这些命令,构建时间从 20 分钟降到 3 分钟不是梦。
自定义任务:部署也能一键完成
虽然 nx 内置了 build/test/serve,但你想加个deploy怎么办?
很简单,写个自定义 Executor 就行。
第一步:定义任务 schema
新建tools/executors/deploy/schema.json:
{ "type": "object", "properties": { "target": { "type": "string", "description": "部署目标环境", "enum": ["staging", "production"] } }, "required": ["target"] }第二步:编写逻辑
tools/executors/deploy/index.ts:
import { ExecutorContext } from '@nrwl/devkit'; export default async function deployExecutor( options: { target: string }, context: ExecutorContext ) { console.log(`🚀 开始部署 ${context.projectName} 到 ${options.target} 环境...`); // 此处调用 AWS S3、Firebase、Netlify CLI 等 // 示例:execSync(`netlify deploy --dir=dist/apps/${context.projectName}`); return { success: true }; }第三步:注册到项目
编辑apps/dashboard/project.json,添加:
"deploy": { "executor": "./tools/executors/deploy", "options": { "target": "staging" } }第四步:运行!
nx deploy dashboard从此,部署也成了标准化流程的一部分。
团队协作最佳实践:避免踩坑的五大原则
nx 很强大,但也容易被“滥用”。以下是我们在真实项目中总结的经验:
1. Lib 分层要合理:按领域,别按技术
❌ 错误做法:
libs/ ├── components/ ← 所有组件堆一起 ├── services/ ← 所有 API 请求 └── models/ ← 所有类型✅ 正确姿势:
libs/ ├── products/ │ ├── ui ← 商品相关组件 │ ├──>"projects": { "dashboard": { "tags": ["scope:marketing", "type:app"] }, "admin-panel": { "tags": ["scope:admin", "type:app"] }, "shared-ui": { "tags": ["scope:shared", "type:ui"] } }然后配合 ESLint 插件@nrwl/nx/enforce-module-boundaries,可以做到:
admin-panel不允许引用marketing相关模块- App 不能直接 import 另一个 App 的代码
- 工具库只能被下层依赖,不能反过来
这样即使新人也不怕搞乱架构。
3. 统一编码风格:Prettier + ESLint 必须上
nx 默认集成 Prettier 和 ESLint,建议在提交前自动格式化:
// package.json "scripts": { "precommit": "nx format:write" }搭配 Husky 使用,保证每一行代码都干净整齐。
4. 定期清理“僵尸项目”
随着迭代推进,总会有些废弃的 lib 或 app 没删干净。
定期运行:
nx graph查看有没有没人引用的“孤岛项目”,及时移除,保持仓库轻盈。
5. 善用缓存:本地 & 远程双保险
nx 支持两种缓存:
- 本地缓存:默认开启,加速重复构建
- 远程缓存(Nx Cloud):团队共享缓存,CI 构建更快
尤其适合多人协作和 CI 场景。哪怕你在公司构建过一次shared-ui,同事拉代码后可以直接下载缓存产物,省去编译时间。
实际工作流演示:新增功能全流程
假设我们要在后台系统中增加“用户权限编辑”功能。
步骤 1:生成功能模块
nx g @nrwl/react:lib users/feature-editor --directory=libs --unitTestRunner=jest生成libs/users/feature-editor目录,包含组件骨架和测试文件。
步骤 2:在主应用中引入
编辑apps/admin-panel/src/app/page.tsx:
import { UserEditor } from '@myorg/users-feature-editor'; function AdminPage() { return ( <div> <h1>管理员面板</h1> <UserEditor /> </div> ); }步骤 3:提交代码触发 CI
git add . git commit -m "feat: add user editor" git push origin feat/user-editorCI 流水线自动执行:
nx affected:apps # 输出:admin-panel nx affected:test # 只测 admin-panel nx affected:build # 只构建成品无需人工干预,安全又高效。
写在最后:nx 不只是一个工具
很多人刚开始觉得 nx 学习成本高,配置复杂。但一旦你经历过:
- 修改一个工具函数,CI 自动识别影响范围;
- 新人入职第一天就能用
nx g生成标准项目; - 重构时看着
nx graph清楚知道谁依赖谁; - 发布前一键部署多个环境……
你会发现,nx 真正带来的不是效率提升,而是一种“可控感”。
它把原本模糊、靠经验判断的工程问题,变成了清晰、可预测、可自动化的流程。
未来,随着 Vite、Turbopack 等新构建工具的普及,nx 也在持续进化,支持更多插件和智能化能力(比如 AI 辅助生成代码边界建议)。可以说,它是目前 JavaScript 生态中最接近“工业级开发标准”的解决方案。
所以,别犹豫了。
现在就开始你的 nx 之旅吧。
当你第一次看到nx affected:build只花 17 秒完成发布准备,而以前要等 8 分钟的时候,你会回来感谢今天的决定。