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