0

I'm using Angular 14 and module federation. I have this in my child application

module.exports = withModuleFederationPlugin({

  name: 'childapp',
  exposes: {
    './app1': './src/app/app.module.ts', 
  },

  shared: {
    ...shareAll({ singleton: true, strictVersion: true, requiredVersion: 'auto' }),
  },

});

In my shell application, I invoke the child using routes like so

  {
    path: 'my-child-path',
    loadChildren: () =>
      loadRemoteModule({
        type: 'module',
        remoteEntry: 'http://localhost:8001/remoteEntry.js',
        exposedModule: './app1',
      }).then((m) => m.AppModule),
  },

However, when I load access the route from the shell application in a browser, I get the JS console error

ERROR Error: Uncaught (in promise): Error: Providers from the `BrowserModule` have already been loaded. If you need access to common directives such as NgIf and NgFor, import the `CommonModule` instead.

In my child app.module.ts file I have

@NgModule({
  declarations: [AppComponent],
  imports: [
    BrowserModule,
    BrowserAnimationsModule,
    ...
  ],
  providers: [
    BrowserAnimationsModule,
    HttpClientModule,
    ...
  ],
  bootstrap: [AppComponent],
})
export class AppModule {}

but if I remove the "BrowserModule" and "BrowserAnimationMoudle" from the child app.module, I get the JS console error

NullInjectorError: NullInjectorError: No provider for Compiler!

when I attempt to load the child application. How do I solve this madness?

Dave
  • 15,639
  • 133
  • 442
  • 830

1 Answers1

0

In child application you should have 2 main modules. 1st - the exposed module ChildModule (this one will be exported to the shell), and 2nd one: usually called AppModule - basically the module that will be doing "shell" logic for the child application, but the very simple one. This module won't be shipped to the application when opening shell, but it will allow opening standalone child application

@NgModule({
  declarations: [RootComponent], // component with just <router-outlet>
  imports: [
    BrowserModule,
    RouterModule.forRoot([
      {
        path: '',
        loadChildren: () => import('./child.module').then((m) => m.ChildModule),
      },
    ]),
    StoreModule.forRoot({}),
  ],
  providers: [],
  bootstrap: [RootComponent],
})
export class AppModule {}

Andrei
  • 10,117
  • 13
  • 21
  • Is it possible to export my AppModule, or barring that, the src/main.ts or src/bootstrap.ts file? – Dave Mar 24 '23 at 20:24
  • in webpack.config. there is `exposes` section that allows you to export anything you want. for example `exposes: { './app1': './src/app/child.module.ts', }, ` – Andrei Mar 24 '23 at 20:41