如何通过模块联合动态加载角度组件?

Pha*_*ate 6 angular webpack-module-federation

我有一个有角度的应用程序,我决定公开这个组件:

new ModuleFederationPlugin({
  
    // For remotes (please adjust)
    name: "app1",
    filename: "app1.js",
    exposes: {
         './Heroes': './/src/app/heroes/heroes.component.ts',
    },        
Run Code Online (Sandbox Code Playgroud)

该组件以这种方式呈现:

import { Component, OnInit } from '@angular/core';

@Component({
 selector: 'app-heroes',
 templateUrl: './heroes.component.html',
 styleUrls: ['./heroes.component.sass']
})
export class HeroesComponent implements OnInit {

  constructor() { }

  ngOnInit(): void {
 }
}
Run Code Online (Sandbox Code Playgroud)

在我的主应用程序中,我想这样做:

<app-heroes></app-heroes>
Run Code Online (Sandbox Code Playgroud)

就像我会做的那样,如果组件是本地的,如何实现这一点?理论上我必须:

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';


@NgModule({
  declarations: [
   AppComponent,
   HeroComponent, //it's not local, so?
 ],
  imports: [
    BrowserModule,
    AppRoutingModule
  ],
   providers: [],
   bootstrap: [AppComponent]
})
 export class AppModule { }
Run Code Online (Sandbox Code Playgroud)

Ser*_*hew 1

我们可以通过编程方式加载组件。

我根据这篇文章添加答案:https://www.angulararchitects.io/aktuelles/module-federation-with-angulars-standalone-components/

还要感谢@JamesEby,他之前已经评论了原始文章的链接。

non-Standalone我们也可以以类似的方式使用组件。(共享组件最好使用SCAM模式)

主机应用程序app.component.html中,定义我们要加载组件的入口点 。

<ng-container #heroesContainer > </ng-container> 
Run Code Online (Sandbox Code Playgroud)

导入组件并将其附加到 中的入口点app.component.ts

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {

  @ViewChild("heroes", { read: ViewContainerRef }) heroesContainer!: ViewContainerRef;

  ngOnInit(): void {
    this.loadHeroes();
  }

  async loadHeroes() {
    // use dynamic import of Typescript to load component from remote application 
    const { HeroesComponent } = await import('app1/Heroes');
    const { instance } = this.heroesContainer.createComponent(HeroesComponent);

    // since it is programmatically loaded we have to bind inputs, handle events like this
    instance.title = 'Mario';
    instance.action.subscribe(() => {
      console.log('Action triggered')
    })
  }
}
Run Code Online (Sandbox Code Playgroud)

假设您正在使用密钥加载远程应用程序app1,并且您正在使用密钥导出组件Heroes(如所讨论的)。

或者,我们可以使用动态模块联合来加载,方法是替换import

const { HeroesComponent } = await loadRemoteModule({
    type: 'module',
    remoteEntry: 'http://localhost:4201/app1.js',
    exposedModule: './Heroes'
});
const { instance } = this.heroesContainer.createComponent(HeroesComponent);
Run Code Online (Sandbox Code Playgroud)