angularmonoreponrwl-nxangular-module-federation

Module federation not working for the first module


I'm facing a strange issue with the App I took over. It's a NX Monorepo with Module Federation and three different Remotes within it. Host app contains following module-federation.manifest.json with remotes definition.

{
  "settings": "http://localhost:4201",
  "map": "http://localhost:4202",
  "data": "http://localhost:4203"
}

Remotes are loaded in the HOST's app.component.ts using this code:

// Template
<host-launcher-shell (remotesChanged)="checkRemotesRouteConfig($event)">
  <router-outlet></router-outlet>
</host-launcher-shell>
// TS
checkRemotesRouteConfig(remotes: Remote[]): void {
  if (!remotes.length) {
    return;
  }
  const defaultRemotePath = `${remotes[0].name}`;
  const routes = this.buildRemoteRoutes(remotes, defaultRemotePath);
  this.router.resetConfig(routes);
}

private buildRemoteRoutes(remotes: Remote[], defaultRemotePath: string): Routes {
  const lazyRoutes: Routes = remotes.map((remote) => ({
    path: remote.name,
    // StackTrace points to the line below
    loadChildren: () => loadRemoteModule(remote.name, './Module').then((m) => m.RemoteEntryModule),
    canLoad: [AuthGuardService],
    data: { breadcrumb: `navigation.breadcrumb.${remote.name}` }
  }));

  const redirectRoute: Route = {
    path: '',
    redirectTo: defaultRemotePath,
    pathMatch: 'full'
  };

  const wildCardRoute: Route = { path: '**', redirectTo: defaultRemotePath };

  return [redirectRoute, ...lazyRoutes, wildCardRoute];
}

Code from the HOST services/components

// Remotes are generated like this - remote.service.ts
prepareRemotes(): Remotes {
  let moduleId = 1;
  // Event though PORTS don't match it, the MAP app is default
  // And should be displayed as first
  this.remotes.push({ id: moduleId++, name: RemotePaths.Map });
  this.remotes.push({ id: moduleId++, name: RemotePaths.Data });
  this.remotes.push({ id: moduleId++, name: RemotePaths.Settings});

  return this.remotes;
}

// And emitted from HOST shell component - shell.component.ts
private loadRemotes(): void {
  this.isLoading = true;
  this.remotes = this.remotesDataService.prepareRemotes();
  
  this.remotesChanged.emit(this.remotes);
  this.isLoading = false;
}

When I added the last application - Data, the Map application stop working. When trying to navigate to it, I'll get the following error:

ERROR Error: Uncaught (in promise): TypeError: error loading dynamically imported module: http://localhost:4202/remoteEntry.mjs

Data App was generated using NX Generate, and aside from defining lint scope and type I did not modified it any way. What I noticed is, that if I generate another App, let's say Topography (port 4204), to take over the Map app, it won't run either, with the same error displayed.

I honestly have no idea where to look for the cause of this issue.


Solution

  • Found out that NX by default does not allow to serve more than 3 applications at once, which is a known issue: nx run-many only serves the first 3 specified projects.

    Updating package.json script fixed it for me:

    "start-dev": "nx run-many --target=serve --all --maxParallel=100",