Nx工作区中如何在一个Nx库模块内导入另一个Nx库模块
报错根因
这个报错和forRoot()调用没有直接关联,绝大多数场景由两类问题触发:
- 跨Nx库导入时使用相对路径深入到目标库的内部文件,没有走Nx配置的库公开入口,导致模块解析失败拿到undefined值
- 两个类库之间存在隐式循环依赖,或者被导入的库没有对外暴露需要复用的声明(指令/组件/模块)
Nx跨库导入模块的正确实现方式
第一步:校验tsconfig路径映射
打开项目根目录的tsconfig.base.json,确认compilerOptions.paths字段下存在两个类库的公开入口映射,正常配置格式如下:{ "compilerOptions": { "paths": { "@你的工作区名称/lib-1": ["libs/lib-1/src/index.ts"], "@你的工作区名称/lib-2": ["libs/lib-2/src/index.ts"] } } }如果缺失对应配置,手动补全即可,Nx默认生成类库时会自动写入该配置,手动移动过库目录才会出现丢失问题。
第二步:使用公开路径跨库导入
禁止在lib-2中使用类似../../lib-1/src/lib/lib1.module的相对路径导入lib1Module,必须使用上面配置的公开别名路径导入:// lib-2 中 lib2.module.ts 顶部的导入语句必须这么写 import { Lib1Module } from '@你的工作区名称/lib-1';所有跨Nx库的导入都必须走库根目录的
index.ts公开入口,直接引用库内部文件是触发该undefined报错的最常见原因。第三步:调整Lib1Module的模块设计,适配forRoot模式
把可复用的声明和全局服务拆分存放:- 给lib-2复用的指令、组件、管道放在
Lib1Module的declarations数组中,同时同步写到exports数组对外暴露 - 需要全局单例的服务全部放到
forRoot()返回的providers数组中,不要直接写在Lib1Module元数据的providers里
参考正确的模块写法:
@NgModule({ declarations: [Lib1ReusableDirective], // lib-2要用的指令放这里 exports: [Lib1ReusableDirective] // 必须导出,外部模块才能使用 }) export class Lib1Module { static forRoot(): ModuleWithProviders<Lib1Module> { return { ngModule: Lib1Module, providers: [/* 所有全局单例服务放在这里,比如Lib1ConfigService */] } } }- 给lib-2复用的指令、组件、管道放在
第四步:按规则配置模块导入
- 主应用
main-application中保留原有Lib1Module.forRoot()导入即可,不需要删除,该配置只会在应用根层级注册全局单例服务 lib-2的Lib2Module中直接导入Lib1Module(不要调用forRoot),此时lib-2内的组件就可以正常使用lib-1导出的指令,也不会重复创建服务实例
- 主应用
第五步:排查循环依赖
执行命令nx dep-graph查看项目依赖关系,如果lib-1和lib-2之间存在循环依赖(即lib-1也反向导入了lib-2的代码),也会触发模块解析为undefined的报错,此时把两边互相依赖的公共代码抽离到第三个独立的共享类库即可。
注意:所有配置修改完成后,停止本地开发服务,删除根目录下的
.nx缓存文件夹后重启服务,避免旧缓存导致修改不生效。
内容的提问来源于stack exchange,提问作者MarciiSautii
相关产品推荐
相关产品推荐

