微前端 - 已创建具有不同配置的平台。请先销毁

Posted

技术标签:

【中文标题】微前端 - 已创建具有不同配置的平台。请先销毁【英文标题】:Micro Frontend - A platform with a different configuration has been created. Please destroy it first 【发布时间】:2021-08-05 06:57:06 【问题描述】:

我正在尝试使用 Angular 和 Webpack Module Federation 为微前端构建 POC。 在此,我创建了一个 shell 应用程序和另一个 mfe1 应用程序,并在特定路由命中渲染该 mfe1,它按预期工作并渲染该应用程序。现在,我正在尝试创建另一个名为 mfe2 的应用程序并进行渲染。在这个 mfe2 中,我正在使用 Angular 元素创建一个 Web 组件并在 shell 应用程序中呈现它。当我这样做时,我面临以下问题

错误:已创建具有不同配置的平台。 请先销毁它。

以下代码执行时

import('mfe2/web-component')
    .then(_ => console.debug(`element loaded!`))
    .catch(err => console.error(`error loading `, err));

我不明白确切的问题出在哪里。我在下面添加所需的代码。

MFE2:

app.module.ts

@NgModule(
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule
  ],
  providers: [],
  bootstrap: []
)
export class AppModule 
  constructor(private injector: Injector) 

  ngDoBootstrap() 
    const ce = createCustomElement(AppComponent, injector: this.injector);
    customElements.define('mfe2-elem', ce);
  


webpack.config.js

module.exports = 
  output: 
    uniqueName: "mfe2",
    publicPath: "auto"
  ,
  optimization: 
    runtimeChunk: false
  ,   
  resolve: 
    alias: 
      ...sharedMappings.getAliases(),
    
  ,
  plugins: [
    new ModuleFederationPlugin(
      
        // For remotes (please adjust)
        name: "mfe2",
        filename: "remoteEntry.js",
        exposes: 
          './web-component': './src/bootstrap.ts',
        ,        
        
        // For hosts (please adjust)
        // remotes: 
        //     "mfe1": "mfe1@http://localhost:3000/remoteEntry.js",

        // ,

        shared: 
          "@angular/core":  singleton: true, strictVersion: true , 
          "@angular/common":  singleton: true, strictVersion: true , 
          "@angular/common/http":  singleton: true, strictVersion: true , 
          "@angular/router":  singleton: true, strictVersion: true ,

          ...sharedMappings.getDescriptors()
        
        
    ),
    sharedMappings.getPlugin()
  ],
;

外壳:

在组件中渲染它:

@Component(
  selector: 'app-mfe2element',
  templateUrl: './mfe2element.component.html',
  styleUrls: ['./mfe2element.component.scss']
)
export class Mfe2elementComponent implements AfterContentInit 

  @ViewChild('vc',  read: ElementRef, static: true )
  vc!: ElementRef;

  constructor()  

  ngAfterContentInit(): void 
    import('mfe2/web-component')
    .then(_ => console.debug(`element loaded!`))
    .catch(err => console.error(`error loading `, err));

    // await import('mfe1/web-components');
    // const element = document.createElement('mfe1-element');
    // document.body.appendChild(element);

    const element = document.createElement('mfe2-elem');
    this.vc.nativeElement.appendChild(element);

  


webpack.config.js

module.exports = 
  output: 
    uniqueName: "shell"
  ,
  optimization: 
    // Only needed to bypass a temporary bug
    runtimeChunk: false
  ,
  plugins: [
    new ModuleFederationPlugin(
        // For remotes (please adjust)
        // name: "shell",
        // filename: "remoteEntry.js",
        // exposes: 
        //     './Component': './/src/app/app.component.ts',
        // ,        
        
        // For hosts (please adjust)
        remotes: 
            "mfe1": "mfe1@http://localhost:3000/remoteEntry.js",
            "mfe2": "mfe2@http://localhost:4000/remoteEntry.js",
        ,

        shared: 
          "@angular/core":  singleton: true, strictVersion: false , 
          "@angular/common":  singleton: true, strictVersion: false , 
          "@angular/router":  singleton: true, strictVersion: false ,

          ...sharedMappings.getDescriptors()
        
        
    ),
    sharedMappings.getPlugin(),
  ],
;

请帮我解决这个问题。

谢谢...

【问题讨论】:

当您创建mfe2 时,您是否能够使用Angular CLI 来生成mfe2,或者您必须繁琐地手动创建mfe2 及其所有文件?我目前正在尝试弄清楚如何向我的 Module Federation 微前端添加更多遥控器。如果您愿意,我的问题就在这里:***.com/questions/68171760/… 【参考方案1】:

从这里获取解决方案: https://github.com/angular-architects/module-federation-plugin/issues/47#issuecomment-845145887

每个共享的 Angular 版本,我们只能创建一个平台。为了记住我们的版本已经有一个共享平台,我们可以将它放入一个全局字典中,将版本号映射到平台实例:

const ngVersion = require('../package.json').dependencies['@angular/core']; // better just take the major version 

(window as any).plattform = (window as any).plattform || ;
let platform = (window as any).plattform[ngVersion];
if (!platform) 
  platform = platformBrowser();
  (window as any).plattform[ngVersion] = platform; 

platform.bootstrapModule(AppModule)
  .catch(err => console.error(err));

将此添加到 shell 和 mfe 中的 bootstrap.ts 将使 mfe 重用现有平台,而不是尝试创建新实例,这将导致您遇到的错误。

【讨论】:

请注意,这是针对每个主要版本的。这意味着如果您的package.json 引用@angular/core: "~12.1.4",它将不适用于版本设置为@angular/core: "~12.2.0" 的MFE,您需要仅在package.json 中将版本引用为主要版本。即@angular/core: "^12.0.0"

以上是关于微前端 - 已创建具有不同配置的平台。请先销毁的主要内容,如果未能解决你的问题,请参考以下文章

从零开始写一个微前端框架-沙箱篇

可能是你见过的最完善的微前端解决方案

微服务项目:尚融宝(14)(前端平台:尚融宝管理系统路由配置)

kubernetes 集群中 cilium 的实践及其网络通信解析

前端实现微信平台实现分享

容器生态系统 (续)