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

Angular微前端路由加载报错:Cannot read properties of undefined (reading 'ɵmod')

Angular微前端路由加载报错:Cannot read properties of undefined (reading 'ɵmod')

问题场景

基于Angular构建微前端,使用以下路由配置代码:

import { loadRemoteModule } from './federation-utils';
import { Routes } from '@angular/router';
import { APP_ROUTES } from '../app.routes';
import { Microfrontend } from '../core/services/microfrontends/microfrontend.types';

export function buildRoutes(options: Microfrontend[]): Routes {
  const lazyRoutes: Routes = options.map((o) => ({
    path: o.routePath,
    loadChildren: () => loadRemoteModule(o).then((m) => m[o.ngModuleName]),
    canActivate: o.canActivate,
    pathMatch: 'full'
  }));

  return [
    ...APP_ROUTES,
    ...lazyRoutes
  ];
}

运行时触发错误:

ERROR Error: Uncaught (in promise): TypeError: Cannot read properties of undefined (reading 'ɵmod')

微前端配置(options)

[
    {
        "remoteEntry": "http://localhost:4204/remoteEntry.js",
        "remoteName": "dashboard",
        "exposedModule": "DashboardModule",
        "displayName": "Dashboard",
        "routePath": "",
        "ngModuleName": "DashboardModule",
        "canActivate": [
            null
        ]
    },
    {
        "remoteEntry": "http://localhost:4202/remoteEntry.js",
        "remoteName": "table",
        "exposedModule": "TablePageModule",
        "displayName": "Table",
        "routePath": "table",
        "ngModuleName": "TablePageModule"
    },
    {
        "remoteEntry": "http://localhost:4201/remoteEntry.js",
        "remoteName": "register",
        "exposedModule": "RegisterPageModule",
        "displayName": "Register",
        "routePath": "signup",
        "ngModuleName": "RegisterPageModule",
        "canActivate": [
            null
        ]
    },
    {
        "remoteEntry": "http://localhost:4203/remoteEntry.js",
        "remoteName": "staticPage",
        "exposedModule": "StaticPageModule",
        "displayName": "Static page",
        "routePath": "static",
        "ngModuleName": "StaticPageModule"
    }
]

控制台输出截图

控制台输出截图1
控制台输出截图2
控制台输出截图3


解决方案

1. 适配ModuleWithProviders返回值

从控制台截图可见,远程模块返回的是ModuleWithProviders类型,而非直接的NgModule类。调整loadChildren回调,提取实际模块:

loadChildren: () => loadRemoteModule(o).then((m) => {
  const targetModule = m[o.ngModuleName];
  // 若为ModuleWithProviders则取module属性,否则直接返回模块
  return targetModule.module || targetModule;
}),

2. 修正远程模块的导出方式

确保远程模块直接导出NgModule类,避免默认导出或嵌套导出:

// 远程模块示例(DashboardModule)
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';

@NgModule({
  imports: [CommonModule],
  declarations: []
})
export class DashboardModule { } // 直接导出类,不要用export default

3. 检查模块联邦的exposes配置

远程应用的webpack配置中,exposes的键需以相对路径格式定义,确保主应用能正确加载:

// 远程应用webpack.config.js
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');

module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      name: 'dashboard',
      filename: 'remoteEntry.js',
      exposes: {
        './DashboardModule': './src/app/dashboard/dashboard.module.ts', // 用相对路径作为键
      },
      // 其他配置...
    }),
  ],
};

同时同步修改options中的exposedModule值为./DashboardModule。

4. 清理无效的路由守卫配置

移除canActivate数组中的null值,避免路由初始化失败:

// 修改前
"canActivate": [null]
// 修改后:保留空数组或删除该字段(无需守卫时)
"canActivate": []

5. 统一Angular版本

主应用与所有微前端应用的@angular/core、@angular/router等核心包版本必须完全一致,版本不匹配会导致模块内部标识(如ɵmod)无法被识别。


内容的提问来源于stack exchange,提问作者user3653474

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 13:02:02