Search code examples
angularangular-modulewebpack-module-federationangular-module-federation

How to use Angular Module Federation to import an entire app


I'm fairly new to Ng Module Federation, but I think I have the gist of it. My issue is that most of the references I've seen either import a single component, or a module that is lazy-loaded in the router. I would like to include an entire mini-app in a page. The general idea is to have iFrame-like behavior without an iFrame.

I have the source app exposing the app.module.ts file and this seems to be working. However, I can't figure out the syntax to import this module and use it as a component within an existing component.

I tried adding loadRemoteModule({...}) to the imports of the module that has the component that will use the nested "app view". But this is an asynchronous function, for one and two, I don't know what to do next.

Does anyone know how to import a module and use its components?


Solution

  • I figured it out and will try to summarize here:

    • Set up the webpack for Module Federation for the Module you wish to expose "as normal". This is where you will get the exposed URL to use below. Reference here: https://module-federation.github.io/blog/get-started#:~:text=%3E%20yarn%20dev-,Start,-Federating

    • In the shell app (the one to consume the federated module):

      • create the "remotes:" section with a name for the remote module and the URL.
           remotes: {
              'myMicroFE@https://mywebsite.com/myMicroFE.js'
           }
        
    • Create the parent component that will house the MicroFE with something like this in the template:

         <app-micro-fe-component></app-micro-fe-component>
      

      and similar code in the .ts file:

       async ngOnInit() {
        const appModule: NgModule = await loadRemoteModule(
        {
         remoteEntry: 'https://mywebsite.com/myMicroFE.js',
         remoteName: 'myMicroFE',
         exposedModule: './AppModule',
        }
       );
       const appModuleRef: NgModuleRef<any> = createNgModuleRef(
        appModule['AppModule'],
        this.injector
       );
       const microFEComponent = this.vcref.createComponent(
        appModuleRef.instance.getComponent()
       );
      // Sample interaction with the component.
      this.renderer.listen('window', 'message', (event) => {
        if (event.data && event.data.providerId) {
          this.microFEClicked.emit(event.data);
        }
       });
       ...
      

    Obviously, names like MyMicroFE are here for readability, you'd use your own names.