Angular 18迁移新构建系统后路由懒加载报ɵcmp未定义错误
Angular新构建系统下动态加载组件出现
ɵcmp未定义错误的解决方案 问题场景
将项目迁移至Angular新构建系统时执行命令:
ng update @angular/cli --name use-application-builder
跳转至包含懒加载模块的路由时触发以下错误:
TypeError: Cannot read properties of undefined (reading 'ɵcmp') at getComponentDef (core.mjs:2462:10) at extractDirectiveDef (core.mjs:2355:10) at core.mjs:2524:96 at Array.map (<anonymous>) at core.mjs:2524:85 at createTView (core.mjs:11384:59) at getOrCreateComponentTView (core.mjs:11333:24) at addComponentLogic (core.mjs:12057:17) at instantiateAllDirectives (core.mjs:11867:5) at createDirectivesInstances (core.mjs:11298:3)
经排查,问题出在懒加载路由组件中的await import动态加载组件代码:
async showConfirmModal(option: MfaOption): Promise<void> { const isEnable = option.status === MfaStatus.INACTIVE; const module = await import('@portalLib/_components/mfa/mfa-modal/mfa-modal.component'); this.modalService.showEntityModal<MfaModalComponent, Partial<MfaModalComponent>>({ nzContent: module.MfaModalComponent, nzData: { option: option, userId: this.userId, email: this.email, isEnable: isEnable, successCallback: () => { option.status = isEnable ? MfaStatus.ACTIVE : MfaStatus.INACTIVE; this.cdRef.detectChanges(); }, }, }); }
解决方案
1. 给动态组件配置专属NgModule并加载模块文件
Angular新构建系统对模块依赖解析更严格,动态加载的组件必须归属已声明的NgModule,且需导出组件:
// mfa-modal.module.ts import { NgModule } from '@angular/core'; import { MfaModalComponent } from './mfa-modal.component'; import { CommonModule } from '@angular/common'; @NgModule({ declarations: [MfaModalComponent], exports: [MfaModalComponent], // 必须导出才能被外部引用 imports: [CommonModule] }) export class MfaModalModule {}
修改动态加载逻辑,改为加载整个模块:
async showConfirmModal(option: MfaOption): Promise<void> { const isEnable = option.status === MfaStatus.INACTIVE; // 加载模块文件而非单个组件文件 const module = await import('@portalLib/_components/mfa/mfa-modal/mfa-modal.module'); this.modalService.showEntityModal<MfaModalComponent, Partial<MfaModalComponent>>({ nzContent: module.MfaModalComponent, nzData: { option: option, userId: this.userId, email: this.email, isEnable: isEnable, successCallback: () => { option.status = isEnable ? MfaStatus.ACTIVE : MfaStatus.INACTIVE; this.cdRef.detectChanges(); }, }, }); }
2. 使用ComponentFactoryResolver确保组件定义初始化
借助Angular内置的组件工厂解析器,强制触发组件定义的加载:
import { ComponentFactoryResolver } from '@angular/core'; // 组件构造函数注入解析器 constructor( private modalService: ModalService, private cfr: ComponentFactoryResolver ) {} async showConfirmModal(option: MfaOption): Promise<void> { const isEnable = option.status === MfaStatus.INACTIVE; const module = await import('@portalLib/_components/mfa/mfa-modal/mfa-modal.component'); // 解析组件工厂,确保组件定义被正确加载 const componentFactory = this.cfr.resolveComponentFactory(module.MfaModalComponent); this.modalService.showEntityModal<MfaModalComponent, Partial<MfaModalComponent>>({ nzContent: componentFactory.componentType, nzData: { option: option, userId: this.userId, email: this.email, isEnable: isEnable, successCallback: () => { option.status = isEnable ? MfaStatus.ACTIVE : MfaStatus.INACTIVE; this.cdRef.detectChanges(); }, }, }); }
3. 调整构建配置避免组件被误优化
在angular.json的构建配置中添加规则,确保动态加载的组件不被树摇优化:
{ "projects": { "your-project-name": { "architect": { "build": { "builder": "@angular-devkit/build-angular:application", "options": { "allowedCommonJsDependencies": ["@portalLib"], // 若组件库为CommonJS格式,添加至允许列表 "preserveSymlinks": true // 使用符号链接库时开启此选项 } } } } } }
4. 预加载动态组件模块
通过路由预加载策略,确保动态组件模块与懒加载路由同步加载:
import { PreloadAllModules } from '@angular/router'; @NgModule({ imports: [RouterModule.forRoot(routes, { preloadingStrategy: PreloadAllModules // 预加载所有模块,或自定义策略仅加载目标模块 })], exports: [RouterModule] }) export class AppRoutingModule {}
内容的提问来源于stack exchange,提问作者Vitalii Litkevich
相关产品推荐
相关产品推荐

