You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 20:27:07