DEV Community

Ruben
Ruben

Posted on

How to load an MFE module from a shell app (Using Angular + Webpack + Module Federation)?

Hi everyone, I have question for you. Do you know how load an MFE (micro front end) remote app, as a module from a shell app? when I try to do so there is an infinite loop. and the module from the MFE does not show. Any tips or ideas on how to accomplish this issue? (Using Angular + Webpack + Module Federation)

// webpack.config.js--SHELL APP 

const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
const path = require("path");

module.exports = {
    output: {
        uniqueName: "portalWebApp",
        publicPath: "auto",
        scriptType: "text/javascript",
    },
    optimization: {
        runtimeChunk: false,
    },
    resolve: {
        alias: {},
    },
    module: {
        rules: [{
            test: /\.html$/,
            use: ["html-loader"],
        }, ],
    },
    experiments: {
        outputModule: true,
    },
    plugins: [
        new ModuleFederationPlugin({
            // For remotes (please Add this 5 Line)
            name: "portalWebApp",
            filename: "remoteEntry.js",
            remotes: {
                astrPortFolioMasterWebApp: "astrPortFolioMasterWebApp@http://localhost:3002/remoteEntry.js",
                mfe1: "mfe1@http://localhost:4001/remoteEntry.js",
            },

            shared: {
                "@angular/core": {
                    singleton: true,
                    strictVersion: true,
                    eager: true
                },
                "@angular/common/": {
                    singleton: true,
                    strictVersion: true,
                    eager: true,
                },
                "@angular/router": {
                    singleton: true,
                    strictVersion: true,
                    eager: true,
                }
                // react: { singleton: true, eager: true },
                // "react-dom": { singleton: true, eager: true },
            },
        }),
    ],
};

// webpack.config.js--SHELL APP--END

// SHELL APP - Route

import { loadRemoteModule } from '@angular-architects/module-federation';
import { WebComponentWrapper, WebComponentWrapperOptions } from '@angular-architects/module-federation-tools';
import { Routes } from '@angular/router';
import { MsalGuard } from '@azure/msal-angular';
// import { MsalGuard } from '@azure/msal-angular';
// import { UserNotAllowedComponent } from './layout/user-not-allowed/user-not-allowed.component';
// import { ServerErrorComponent } from './layout/server-error/server-error.component';

export const routes: Routes = [{
        path: '',
        pathMatch: 'full',
        loadChildren: () =>
            import('./content-providers/content-provider.module').then(
                (m) => m.ContentProviderModule
            ),
        canActivate: [MsalGuard],
    },
    {
        path: 'mfe1',
        loadChildren: () => {
            return loadRemoteModule({
                    type: 'module',
                    remoteEntry: 'http://localhost:4001/remoteEntry.js',
                    exposedModule: './OrderModule',
                })
                .then((m) => m.OrderModule)
                .catch((e) => console.log(e));
        },
    },
    {
        path: 'astrPortFolioMasterWebApp',
        loadChildren: () => {
            return loadRemoteModule({
                    type: 'module',
                    remoteEntry: 'http://localhost:3002/remoteEntry.js',
                    exposedModule: './astrPortFolioMasterWebAppModule',
                })
                .then((m) => m.astrPortFolioMasterWebAppModule)
                .catch((e) => console.log(e));
        },
    },
    {
        path: 'angular1',
        component: WebComponentWrapper,
        data: {
            remoteEntry: 'https://nice-grass-018f7d910.azurestaticapps.net/remoteEntry.js',
            remoteName: 'angular1',
            exposedModule: './web-components',
            elementName: 'angular1-element',
        }
        as WebComponentWrapperOptions,
    },
    {
        path: 'react1',
        component: WebComponentWrapper,
        data: {
            remoteEntry: 'https://witty-wave-0a695f710.azurestaticapps.net/remoteEntry.js',
            remoteName: 'react',
            exposedModule: './web-components',
            elementName: 'react-element',
        }
        as WebComponentWrapperOptions,
    },
    {
        path: 'vue',
        component: WebComponentWrapper,
        data: {
            remoteEntry: 'https://mango-field-0d0778c10.azurestaticapps.net/remoteEntry.js',
            remoteName: 'vue',
            exposedModule: './web-components',
            elementName: 'vue-element',
        }
        as WebComponentWrapperOptions,
    },
];


// SHELL APP - Route 

// webpack.config.js--MFE / REMOTE APP 

const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
const { shareAll, SharedMappings } = require("@angular-architects/module-federation/webpack");
const Path = require("path");
const sharedMappings = new SharedMappings();

sharedMappings.register(
    Path.join(__dirname, 'tsconfig.json'), []
)
module.exports = {
    output: {
        uniqueName: "astrPortFolioMasterWebApp",
        publicPath: "auto",
        scriptType: "text/javascript",
    },
    optimization: {
        runtimeChunk: false
    },
    resolve: {
        alias: {
            ...sharedMappings.getAliases(),
        }
    },
    experiments: {
        outputModule: true
    },
    plugins: [
        new ModuleFederationPlugin({

            // For remotes (please Add this 5 Line)
            name: "astrPortFolioMasterWebApp",
            filename: "remoteEntry.js",
            exposes: {
                './astrPortFolioMasterWebAppModule': './src/app/layout/layout.module.ts',
            },

            shared: {
                "@angular/core": {
                    singleton: true,
                    strictVersion: true,
                    eager: true
                },
                "@angular/common/": {
                    singleton: true,
                    strictVersion: true,
                    eager: true
                },
                "@angular/router": {
                    singleton: true,
                    strictVersion: true,
                    eager: true
                },
            }
        }),
        sharedMappings.getPlugin()
    ]
};

// webpack.config.js--MFE / REMOTE APP - END 

// MFE - Remote - Route 

import { Routes } from '@angular/router';
import { MsalGuard } from '@azure/msal-angular';
import { UserNotAllowedComponent } from './layout/user-not-allowed/user-not-allowed.component';
import { ServerErrorComponent } from './layout/server-error/server-error.component';

export const routes: Routes = [
    // {
    //   path: '',
    //   pathMatch: 'full',
    //   redirectTo: 'portfolio'
    // },
    {
        path: 'portfolio',
        loadChildren: () =>
            import('./layout/layout.module').then((m) => m.MainLayoutModule),
        canActivate: [MsalGuard]
    },

    {
        path: 'usernotallowed',
        component: UserNotAllowedComponent,
    },

    {
        path: '**',
        component: ServerErrorComponent,
    },
];

// MFE - Remote - Route - END 
Enter fullscreen mode Exit fullscreen mode

Top comments (0)