6

I have an angular app where I decided to expose this component:

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

The component renders in this way:

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 {
 }
}

In my main app I'd like to do this:

<app-heroes></app-heroes>

Like I would do if the component was local, how to achieve this? In theory I would have to:

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 { }
Phate
  • 6,066
  • 15
  • 73
  • 138
  • Here is a helping repo that helped me to use module federation in my project: https://github.com/module-federation/module-federation-examples/tree/master/angular12-microfrontends – OLO Jun 24 '21 at 21:49
  • https://github.com/manfredsteyer/module-federation-with-angular-dynamic-workflow-designer this has an example where it is exposing a component via remoteEntry.js – Zameer Fouzan Aug 16 '21 at 15:27
  • Tutorial on how to expose components rather than modules via module federation, this is the tutorial for the github repo that @ZameerFouzan gives above: https://www.angulararchitects.io/aktuelles/module-federation-with-angulars-standalone-components/ – James Eby Sep 20 '22 at 03:10

1 Answers1

1

We can programmatically load components.

I am adding answer based on this article:https://www.angulararchitects.io/aktuelles/module-federation-with-angulars-standalone-components/

Also credits to @JamesEby who already commented the link to the original article earlier.

We can use non-Standalone components as well in a similar way. (It is better to use SCAM pattern for shared components)

In the Host application, define the entry point in app.component.html where we want to load the component.

<ng-container #heroes> </ng-container> 

Import the component and attach it to the entry point in app.component.ts.

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

  @ViewChild("heroes", { read: ViewContainerRef }) heroes!: 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.header.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')
    })
  }
}

Provided that you are loading the remote application with key app1 and you are exporting your component with the key Heroes ( as in question ).

Alternatively, we can load using Dynamic Module Federation by replacing import with

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