title: Code structure when dynamically load a micro frontend via Module Federation
body: <p>I picked up the git examples of <a href="https://www.angulararchitects.io/en/aktuelles/multi-framework-and-version-micro-frontends-with-module-federation-the-good-the-bad-the-ugly/" rel="nofollow noreferrer">https://www.angulararchitects.io/en/aktuelles/multi-framework-and-version-micro-frontends-with-module-federation-the-good-the-bad-the-ugly/</a> further referenced as Ex. 1 and <a href="https://www.angulararchitects.io/en/aktuelles/dynamic-module-federation-with-angular/" rel="nofollow noreferrer">https://www.angulararchitects.io/en/aktuelles/dynamic-module-federation-with-angular/</a> further referenced as Ex. 2.</p>
  <p>Ex. 1 has multiple angular projects in it. For the sake of simplification just use the shell and the mfe1 (micro frontend 1). The example uses a <code>package.json</code> and <code>angular.json</code> for each project, which I want to use either because in the real world, we maybe have plenty of micro frontends and do not want to update all or manage all dependecies at one point. The culprit for me in this example is the fact that it uses a <code>WrapperComponent</code> and a <code>registry.ts</code>. When a route is activated it lazy loads via this function:</p>
  <pre class="lang-js prettyprint-override"><code>    ngAfterContentInit(): void {
      
          const elementName = this.route.snapshot.data['elementName'];
          const importName = this.route.snapshot.data['importName'];
      
          const importFn = registry[importName];
          importFn()
            .then(_ =&gt; console.debug(`element ${elementName} loaded!`))
            .catch(err =&gt; console.error(`error loading ${elementName}:`, err));
      
          const element = document.createElement(elementName);
          this.vc.nativeElement.appendChild(element);
      
      }
  </code></pre>
  <p>The <code>registry</code> contains a mapping like</p>
  <pre class="lang-js prettyprint-override"><code>export const registry = {
      mfe1: () =&gt; import('mfe1/web-components')
  };
  </code></pre>
  <p>AFAIK there happens some &quot;webpack magic&quot; to do the import and <code>mfe1</code> is mapped to a different host via <code>webpack.config.js</code>. That means I need to know the the number and names of the micro frontends at compile time.</p>
  <p>Ex. 2 uses a dynamic approach by using a <code>LookupService</code></p>
  <pre class="lang-js prettyprint-override"><code>export class LookupService {
      lookup(): Promise&lt;Microfrontend[]&gt; {
          return Promise.resolve([
              {
                  // For Loading
                  remoteEntry: 'http://localhost:3000/remoteEntry.js',
                  remoteName: 'mfe1',
                  exposedModule: './Module',
  
                  // For Routing
                  displayName: 'Flights',
                  routePath: 'flights',
                  ngModuleName: 'FlightsModule'
              }
          ] as Microfrontend[]);
      }
  }
  </code></pre>
  <p>and a function to build the routes</p>
  <pre class="lang-js prettyprint-override"><code>export function buildRoutes(options: Microfrontend[]): Routes {
  
      const lazyRoutes: Routes = options.map(o =&gt; ({
          path: o.routePath,
          loadChildren: () =&gt; loadRemoteModule(o).then(m =&gt; m[o.ngModuleName])
      }));
  
      return [...APP_ROUTES, ...lazyRoutes];
  }
  </code></pre>
  <p>Now, I want to combine both approaches. So, I copied the approach for Ex. 2 into Ex. 1 and now struggling with the following.</p>
  <p>When simply exposing the <code>AppModule</code> of <code>mfe1</code> and dynamically load it, I have multiple <code>RouterModule.forRoot()</code> calls, which is not avoidable because <code>mfe1</code> and <code>shell</code> should also work as standalone. This leads to an error. So, I simply made a &quot;dummy&quot; <code>AppModule</code>, call <code>RouterModule.forRoot()</code> and have a path directing to another module, which is using only <code>RouterModule.forChild()</code> (called the <code>FlightsModule</code> in example). This other <code>FlightsModule</code> is loaded dynamically in <code>shell</code>, hence no more multiple calls to <code>RouterModule.forRoot()</code>. Is this necessary or is there another option?</p>
  <p>Because I only can load a &quot;submodule&quot; of <code>mfe1</code>, I need to shift the content of several common files. <code>mfe1/src/styles.css</code> for global styles needs to be moved to a component always activated by the route with <code>encapsulation: ViewEncapsulation.None</code> to make it globally accessible e.g. when using <code>ngx-toastr</code> this is needed. The <code>styles</code> option in the <code>angular.json</code> can not be used by a micro frontend because it will break when loaded over the <code>shell</code>. Everything normally imported and declared in <code>AppModule</code> needs to be shifted to the submodule. And so on...</p>
  <p>In the end, I think this approach is definetly not the best but I tried so many different things and none, except this one, is working.</p>