cj devin
cj devin

Reputation: 1375

dynamic @angular-architects/module-federation with Multi repo(host repo,remote repo), doesn't show remote MFE app content in host app

I am using Angular v14.1.1. And I have two repo host app and remote app. I am trying to apply module-federation plugin in each repo project. But facing issue seems remote app remoteEntry.js loaded in network but content not showing in UI.

Repo1:Remote App configuration:

webpack.config.js

const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
const mf = require("@angular-architects/module-federation/webpack");
const path = require("path");
const share = mf.share;

const sharedMappings = new mf.SharedMappings();
sharedMappings.register(
  path.join(__dirname, '../../tsconfig.base.json'),
  [/* mapped paths to share */]);

module.exports = {
  output: {
    uniqueName: "remotemfe1",
    publicPath: "auto"
  },
  optimization: {
    runtimeChunk: false
  },   
  resolve: {
    alias: {
      ...sharedMappings.getAliases(),
    }
  },
  experiments: {
    outputModule: true
  },
  plugins: [
    new ModuleFederationPlugin({
        library: { type: "module" },

        // For remotes (please adjust)
        name: "remotemfe1",
        filename: "remoteEntry.js",
        exposes: {
            './Module': './apps/remotemfe1/src/app/app.module.ts',
        },        
        
        // For hosts (please adjust)
        // remotes: {
        //     "mfe1": "http://localhost:3000/remoteEntry.js",

        // },

        shared: share({
          "@angular/core": { singleton: true, strictVersion: true, requiredVersion: 'auto' }, 
          "@angular/common": { singleton: true, strictVersion: true, requiredVersion: 'auto' }, 
          "@angular/common/http": { singleton: true, strictVersion: true, requiredVersion: 'auto' }, 
          "@angular/router": { singleton: true, strictVersion: true, requiredVersion: 'auto' },

          ...sharedMappings.getDescriptors()
        })
        
    }),
    sharedMappings.getPlugin()
  ],
};

app.module.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { TestComponent } from './app.component';

@NgModule({
  declarations: [TestComponent],
  imports: [
    BrowserModule
  ],
  providers: [],
  bootstrap: [TestComponent],
})
export class AppModule {}

Repo2:Host App Configuration:

webpack.config.js

const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
const mf = require("@angular-architects/module-federation/webpack");
const path = require("path");
const share = mf.share;

const sharedMappings = new mf.SharedMappings();
sharedMappings.register(
  path.join(__dirname, '../../tsconfig.base.json'),
  [/* mapped paths to share */]);

module.exports = {
  output: {
    uniqueName: "hostmf",
    publicPath: "auto"
  },
  optimization: {
    runtimeChunk: false
  },   
  resolve: {
    alias: {
      ...sharedMappings.getAliases(),
    }
  },
  experiments: {
    outputModule: true
  },
  plugins: [
    new ModuleFederationPlugin({
        library: { type: "module" },

        // For remotes (please adjust)
        // name: "hostmf",
        // filename: "remoteEntry.js",
        // exposes: {
        //     './Component': './apps/hostmf/src/app/app.component.ts',
        // },        
        
        // For hosts (please adjust)
        // remotes: {
        //     "remotemfe1": "http://localhost:3000/remoteEntry.js",
        // },

        shared: share({
          "@angular/core": { singleton: true, strictVersion: true, requiredVersion: 'auto' }, 
          "@angular/common": { singleton: true, strictVersion: true, requiredVersion: 'auto' }, 
          "@angular/common/http": { singleton: true, strictVersion: true, requiredVersion: 'auto' }, 
          "@angular/router": { singleton: true, strictVersion: true, requiredVersion: 'auto' },

          ...sharedMappings.getDescriptors()
        })
        
    }),
    sharedMappings.getPlugin()
  ],
};

host app app.module.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { AppComponent } from './app.component';
import { RouterModule } from '@angular/router';
import { loadRemoteModule } from '@angular-architects/module-federation';

@NgModule({
  declarations: [AppComponent],
  imports: [
    BrowserModule,
    RouterModule.forRoot([
      {
        path: 'remotemfe1',
        loadChildren: () =>
            loadRemoteModule({
                type: 'module',
                remoteEntry: 'http://localhost:4201/remoteEntry.js',
                exposedModule: './Module'
            })
            .then(m => {
              console.log(m);
              return m.AppModule;
            })
    }
    ]),
  ],
  providers: [],
  bootstrap: [AppComponent],
})
export class AppModule {}


//**app.component.ts**

import { Component } from '@angular/core';

@Component({
  selector: 'hostrepo-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss'],
})
export class AppComponent {
  title = 'hostmf';
}

app.component.html

host app works!
<router-outlet></router-outlet>

hostapp index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>Hostmf</title>
    <base href="/" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <link rel="icon" type="image/x-icon" href="favicon.ico" />
  </head>
  <body>
    <hostrepo-root></hostrepo-root>
  </body>
</html>

Host app running on http://localhost:4200 and remote app http://localhost:4201

Issue: when i am try to load http://localhost:4200/remotemfe1 in UI only show host app works! without remoteapp content but in dev tool network tab remoteEntry.js file being loaded.

What could be the issue? How to solve issue. Could you please any help? Thanks.

Upvotes: 1

Views: 1683

Answers (1)

cj devin
cj devin

Reputation: 1375

May be other solution available as well but I got the solution like After added RouteModule.forChild in remote MFE app imports. MFEs app content showing in host app.

 RouterModule.forChild([{
      path:'',
      component:TestComponent
    }])

Upvotes: 2

Related Questions