Francesco
Francesco

Reputation: 10870

Angular 14 with Module Federation library not working if one remote is not available

We have an Angular project with multiple micro-frontends using Manfred Steyer's module federation library.

After migrating from module federation v12 to v14, the application stops working if one remote endpoint is unavailable. In contrast, with the old version, the application kept working except the not available micro-frontends.

Our webpack config file for the shell part:

const { share, withModuleFederationPlugin } = require('@angular-architects/module-federation/webpack');

module.exports = withModuleFederationPlugin({
  name: 'shell',
  filename: 'shell.js',

  sharedMappings: ['frontend/mfe-shared'],

  exposes: {
    './Module': 'apps/shell/src/app/app.module.ts',
  },
  remotes: {
    dashboard: `http://localhost:4201/dashboard.js`,
    offers: `http://localhost:4206/offers.js`,
    clients: `http://localhost:4206/clients.js`,
  },    
  shared: share({
    '@angular/core': { singleton: true, strictVersion: true, requiredVersion: '14.2.12' },
    '@angular/common': { singleton: true, strictVersion: true, requiredVersion: '14.2.12' },
    '@angular/common/http': { singleton: true, strictVersion: true, requiredVersion: '14.2.12' },
    '@angular/router': { singleton: true, strictVersion: true, requiredVersion: '14.2.12' },
    'ngx-webstorage-service': { singleton: true, strictVersion: true },
  }),
});

The webpack config file for the dashboard remote, for instance:

const { share, withModuleFederationPlugin } = require('@angular-architects/module-federation/webpack');

module.exports = withModuleFederationPlugin({
  name: 'dashboard',
  filename: 'dashboard.js',

  sharedMappings: ['frontend/mfe-shared'],
  exposes: {
    './Module': 'apps/dashboard/src/app/app.module.ts',
  },

  shared: share({
    '@angular/core': { singleton: true, strictVersion: true, requiredVersion: '14.2.12' },
    '@angular/common': { singleton: true, strictVersion: true, requiredVersion: '14.2.12' },
    '@angular/common/http': { singleton: true, strictVersion: true, requiredVersion: '14.2.12' },
    '@angular/router': { singleton: true, strictVersion: true, requiredVersion: '14.2.12' },
    'ngx-webstorage-service': { singleton: true, strictVersion: true },
  }),
});

Our routes:

const routes: Routes = [
  {
    path: 'dashboard',
    loadChildren: () => import('dashboard/Module').then(({ AppModule }) => AppModule),
  },
  {
    path: 'client',
    loadChildren: () => import('partner/Module').then(({ AppModule }) => AppModule),
  },
  {
    path: 'offers',
    loadChildren: () => import('iam/Module').then(({ IamModule }) => IamModule),
  }
];

@NgModule({
  imports: [
    RouterModule.forRoot(routes, { onSameUrlNavigation: 'reload', relativeLinkResolution: 'legacy', paramsInheritanceStrategy: 'always' }),
  ],
  exports: [RouterModule],
})
export class AppRoutingModule {}

With the current configuration, if the dashboard remote is not available, the whole application displays only a blank page, even if all remote modules, but dashboard, have been downloaded. Is anything missing in the new configuration? Aside from this aspect, the application works fine, if all remotes are available.

Our versions:

Upvotes: 0

Views: 2931

Answers (1)

Francesco
Francesco

Reputation: 10870

Using loadRemoteModule and moving all remotes there allowed preventing the app to stop working if a single micro frontend was not responding.

Our shell routing module:

const routes: Routes = [
  {
    path: 'dashboard',
    loadChildren: () => loadRemoteModule(getConfig('dashboard')).then((m) => m.AppModule),
  },
// ....

Our webpack.config.js for the shell:

module.exports = withModuleFederationPlugin({
  name: 'shell',
  filename: 'shell.js',

  exposes: {
    './Module': 'apps/shell/src/app/app.module.ts',
  },
  remotes: {
    // Remotes are loaded as remote module in shell/app.routing file
  },
 // ...

Upvotes: 1

Related Questions