如何像Lerna一样使用NX构建多框架Monorepo?
核心配置思路
NX完全可以实现你要的「每个项目独立package.json、跨框架兼容、微前端路由+状态共享」需求,关键是采用独立项目模式结合Module Federation微前端架构,同时利用NX的任务管理替代Lerna的核心功能。
1. 初始化NX Workspace(空模板)
先创建一个空的NX工作区,避免预设模板强制统一依赖版本:
npx create-nx-workspace@latest my-monorepo --preset=empty --package-manager=pnpm
用pnpm可以更好地支持项目级独立依赖版本,同时共享公共依赖以节省空间。
2. 添加独立项目(每个项目带专属package.json)
每个应用/服务都放在apps/目录下,单独维护自己的package.json,支持不同框架或Angular版本:
示例:添加Angular 16宿主应用
# 创建宿主应用,开启路由 nx generate @nx/angular:app host-project1 --routing=true --style=css # 进入项目目录,生成独立package.json cd apps/host-project1 pnpm init -y # 手动添加Angular 16依赖(或直接迁移NX生成的依赖) pnpm add @angular/core@16 @angular/cli@16 ...
示例:添加Angular 16远程应用(landingEditor)
nx generate @nx/angular:app landingEditor --routing=true --style=css cd apps/landingEditor pnpm init -y # 如需用Angular 15,直接指定版本 pnpm add @angular/core@15 @angular/cli@15 ...
后续添加React/Next.js项目
同理,用NX对应的生成器创建项目,再生成独立package.json:
# React应用 nx generate @nx/react:app react-app # Next.js应用 nx generate @nx/next:app next-app
每个项目的package.json独立维护依赖版本,NX会自动识别项目间的依赖关系,同时支持单独运行每个项目:
# 单独运行宿主应用 cd apps/host-project1 && pnpm start # 单独运行远程应用 cd apps/landingEditor && pnpm start
3. 微前端路由配置(宿主路由到远程应用)
用NX集成的Module Federation实现宿主应用加载远程应用模块,满足路由需求:
给宿主应用配置Module Federation Host
nx add @nx/angular:module-federation --project=host-project1 --type=host
修改宿主的module-federation.config.ts,注册远程应用:
export default { name: 'host-project1', remotes: [ ['landingEditor', 'http://localhost:4201/remoteEntry.js'], ['searchEngine', 'http://localhost:4202/remoteEntry.js'], ['editor', 'http://localhost:4203/remoteEntry.js'], ], };
给远程应用配置Module Federation Remote
以landingEditor为例:
nx add @nx/angular:module-federation --project=landingEditor --type=remote
修改远程应用的module-federation.config.ts,暴露根模块:
export default { name: 'landingEditor', exposes: { './Module': './src/app/app.module.ts', }, };
宿主应用配置路由
在host-project1/src/app/app-routing.module.ts中添加远程路由:
const routes: Routes = [ { path: 'landing-editor', loadChildren: () => import('landingEditor/Module').then(m => m.AppModule), }, // 同理配置searchEngine、editor的路由 ];
4. 跨应用状态共享
通过Module Federation共享状态管理服务,实现宿主与远程应用的状态同步:
- 在宿主应用中创建状态服务(比如NgRx Store或自定义服务),并在
module-federation.config.ts中共享相关依赖:
// 宿主的module-federation.config.ts shared: { '@angular/core': { singleton: true, strictVersion: true }, '@ngrx/store': { singleton: true, strictVersion: true }, // 共享自定义状态服务所在的lib '@my-monorepo/shared-state': { singleton: true, strictVersion: true }, },
- 远程应用导入宿主共享的状态服务,直接使用宿主的Store或状态实例,实现状态同步。
5. 纳入后端项目(规避前后端版本差异)
添加独立的后端项目(比如NestJS),同样维护自己的package.json:
nx generate @nx/nest:app api cd apps/api pnpm init -y # 独立安装后端依赖 pnpm add @nestjs/core@10 ...
后端项目可单独运行、部署,与前端项目完全隔离,避免版本冲突。
6. 替代Lerna的核心功能
NX提供了与Lerna一致的依赖管理、批量执行、发布能力:
- 批量执行脚本:替代
lerna runnx run-many --target=build --projects=host-project1,landingEditor - 依赖可视化:替代
lerna lsnx dep-graph - 发布项目:替代
lerna publishnx publish --project=landingEditor --version=1.0.0
内容的提问来源于stack exchange,提问作者Jason Rich Darmawan

