如果你是一个有多个前端项目在跑的开发者,肯定有过这种崩溃时刻:要改一个公共的时间格式化工具函数,得同时登三个Git仓库,每个仓库都要改一遍,然后分别提交、打标签、发布npm包,最后还要在另外两个项目里更新依赖——整整半天就耗在这一件事上,还怕漏改某个仓库的版本,甚至有一次因为漏改了H5仓库的函数,导致线上订单页面时间显示错误,被运营同学追着问了一下午。这时候你就会发现,传统的多仓库架构已经撑不住了,该考虑换成Nx的Monorepo了。
一、什么时候该考虑从多仓库转到Nx Monorepo
1.1 多仓库的典型痛点
我之前待过的电商公司,三个项目分别是用户端H5、商家管理后台、运营中台,各占一个Git仓库。光是公共工具函数就复制了12份,每个项目的构建脚本、测试脚本都不一样,CI流程要分别配置三次,每次合并代码都要处理不同仓库的分支冲突,协作效率特别低。而且每次要做统一的UI规范升级,改一个公共按钮,就要在三个仓库各改一次,分别构建、发布,稍不注意就会漏改,给线上埋坑。
1.2 适配Nx迁移的核心场景
如果你的项目满足以下任意一条,都适合考虑迁移:项目之间有大量复用的代码、组件或工具函数;需要统一的构建、部署和测试流程;团队协作频繁,经常跨项目改代码;想提升CI/CD的效率,减少重复构建;想把分散的工具链(如ESLint、Prettier)统一管理。
二、Nx Monorepo相比多仓库的核心优劣
2.1 优点
最大的好处是代码复用更简单,不用靠npm包发布来共享,直接引用共享库的代码,改一次就能同步到所有项目,不用再复制粘贴;然后是构建和测试快,Nx会自动缓存之前的构建和测试结果,只跑修改过的代码部分,原来构建三个项目要12分钟,现在只需要1.5分钟;还有统一工具链,所有项目用同一套代码规范,不用每个仓库单独配置ESLint或Prettier;最后是CI流程简化,一次配置就能覆盖所有项目,还能自动只跑改动的项目,节省CI时间。
2.2 缺点
初期需要花时间把现有的项目结构转到Monorepo,还要学习Nx的常用命令和配置规则,刚迁移的时候可能会遇到依赖版本不兼容的问题,需要花时间统一调整各个项目的依赖;另外,Monorepo的仓库本身会比多仓库大一点,但现在的硬盘空间完全能承载,不算问题。
三、从多仓库转Nx Monorepo的分步实战
3.1 本地环境准备
首先在本地安装Nx,用React技术栈初始化一个Monorepo workspace,命令如下:
npx create-nx-workspace@latest my-shop --preset=react --appName=admin --no-nx-cloud
这里的--preset=react指定用React技术栈,--appName=admin是第一个项目的名字,--no-nx-cloud不用Nx的云端服务,适合内部项目,不会有额外成本。初始化完成后,你会看到新的项目结构,apps文件夹放三个项目:admin、h5、中台,libs文件夹放所有共享的代码(组件、工具函数、接口封装等)。
3.2 迁移现有项目的核心模块
把原来三个项目里的共享模块,比如按钮组件、工具函数,统一移到libs文件夹里,比如原来admin项目里的Button组件,现在移到libs/common-ui/src/lib/Button文件夹,代码示例如下:
// 技术栈:React 18 + Nx 16
// 示例:迁移后共享的Button组件,供所有项目引用
import React from 'react';
// 这个组件原来在三个项目里各有一份,现在统一维护,改一次全项目生效
export const CommonButton = ({ label, onClick, type = 'primary' }) => {
const style = type === 'primary'
? { backgroundColor: '#1890ff', color: '#fff' }
: { backgroundColor: '#fff', color: '#1890ff', border: '1px solid #1890ff' };
return (
<button
style={{ padding: '8px 16px', borderRadius: '4px', ...style }}
onClick={onClick}
>
{label}
</button>
);
};
迁移完成后,原来项目里的引用路径要改成Monorepo的共享库路径,比如原来admin里的引用是import Button from '../../src/components/Button',现在改成import { CommonButton } from '@my-shop/common-ui',这样就不用复制代码了。
3.3 调整构建和测试脚本
原来多仓库里,每个项目的构建命令是单独的,比如admin是npm run build,h5是npm run build:prod,现在用Nx的统一命令,自动处理依赖的共享模块,示例如下:
// 技术栈:Shell 命令
// 示例:用Nx构建admin项目,自动构建它依赖的共享库
nx build admin --prod --with-deps
这里的--with-deps参数会自动构建admin项目依赖的共享库(比如common-ui、utils),不用手动调整构建顺序,测试的话用nx test admin,只会跑admin项目修改过的测试用例,不用跑所有项目的测试,节省时间。
3.4 处理依赖冲突
原来三个项目的依赖版本不一样,比如admin用Ant Design 4.x,h5用Ant Design 3.x,中台用自己封装的老版本组件,现在要把所有项目的依赖统一到根目录的package.json里,避免版本冲突,示例如下:
// 技术栈:JSON 配置
// 根目录package.json的dependencies部分,统一所有项目的依赖版本
{
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0",
"antd": "^5.12.0", // 统一到5.x,兼容三个项目,同时支持新功能
"axios": "^1.6.2",
"dayjs": "^1.11.10"
}
}
迁移前要先在本地测试所有项目,确保统一依赖后都能正常运行,再提交到仓库,避免线上出现兼容问题。
四、迁移过程中的核心注意事项
4.1 分批次迁移,不要一次性上线
不要把所有项目同时转到Nx Monorepo,建议先转核心项目(比如管理后台),跑1-2个月,确认没有大问题后,再转次要项目(比如H5),最后转边缘项目,这样即使踩坑也只会影响一个项目,不会导致所有业务中断。我所在团队就是先转了管理后台,用了3周测试没问题,再转H5,2周后转中台,总共花了6周,比一次性迁移出一堆问题要稳得多。
4.2 保留旧多仓库的备份
迁移过程中,旧的多仓库至少要保留3个月,不要马上删除,万一Nx里出现解决不了的问题,或者线上出bug,能快速切回旧的架构,避免业务停摆。我之前帮公司做迁移的时候,旧仓库留了半年,最后确认没问题才删掉,这样心里踏实。
4.3 给团队做简单培训
Nx的命令其实很简单,常用的就几个:nx serve 项目名启动开发服务器,nx build 项目名构建生产版本,nx test 项目名运行测试,nx lint 项目名检查代码规范。写个简单的小文档,贴在团队的wiki上,大家花10分钟就能学会,不用怕复杂。
4.4 保留Git历史记录
用Nx的官方迁移脚本(nx generate @nx/workspace:move)迁移现有项目,会自动把旧仓库的Git commit合并到新的Monorepo里,不会丢失代码的提交历史,这样以后查问题的时候,还能看到原来的修改记录,不用担心历史丢失的问题。
4.5 调整CI/CD脚本
原来每个项目的CI脚本是单独配置的,现在改成Nx的命令,只跑修改过的项目,比如用GitHub Actions的话,示例脚本如下:
// 技术栈:GitHub Actions YAML
// 示例:CI脚本自动只构建改动的项目,减少CI时间
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: nrwl/nx-set-shas@v3 # Nx官方Action,计算本次改动的项目
- run: nx affected:build --prod # 只构建本次改动的项目,节省时间
原来的CI时间是20分钟,改成这个脚本后,CI时间降到5分钟,效率提升了好几倍。
五、实战总结
迁移完Nx Monorepo之后,最明显的变化是开发效率提升了很多:改一个公共组件,从原来的半天变成10分钟,不用再担心漏改;构建时间从12分钟降到1.5分钟,开发等待的时间少了很多;跨项目协作的成本也降了,原来要在三个仓库发PR,现在只需要在Monorepo里改一次,合并一个PR就行。当然,迁移的时候会遇到一些小问题,比如依赖版本调整、Nx命令的使用,只要按分批次迁移、保留备份的思路来,很快就能适应。对于有多个关联前端项目的团队来说,Nx Monorepo确实是能解决很多痛点的架构方案。
评论
围绕“Nx项目迁移实战:从传统多仓库架构切换至Nx Monorepo的注意事项”参与讨论