I have created one Angular MFA Architecture app which have shell and remote apps which build on top of Angular V17.1. I have to create this below mentioned shell/host app routing to access AngularJS V1.8 with module federation custom element which exposed in "http://localhost:4203/remoteEntry.js" as web component and i can see the js code while hit this remote url. we are using Native federation because of ng v17 use esbuild instead of webpack in angular V17.1.
When we route with angular V17 and native-federation, it was not working and throw below error to access angularjs application http://localhost:4203/remoteEntry.js as mentioned below, but i can see file exposed javascript file while hit this same url in browser. there is no more cors issue and i can find one error while tried to access route through MFA shell app.
This is NG v17 MFA app route to access angularjs remoteEntry.js
{
path: 'angularjs',
loadChildren: () =>
loadRemoteModule({
remoteEntry: 'http://localhost:4203/remoteEntry.js',
remoteName: 'angularjs',
exposedModule: './web-components',
}).then((m) => m.helloComponent),
},
app\app.module.mjs // Custom Element in a [email protected]
angular
.module("app", []).component("helloComponent", {
controller: function () {
this.message = "Hi i'm from AngularJS!";
},
template: `
<h1 style="color:#000">
{{$ctrl.message}}
<img src="https://angular.io/assets/images/logos/angularjs/AngularJS-Shield.svg" height="30">
</h1>
`
})
export class MfeAngularJs extends HTMLElement {
connectedCallback() {
const root = document.createElement("hello-component");
this.appendChild(root);
// angular.bootstrap(root, ["app"]);
}
}
customElements.define("angularjs-element", MfeAngularJs);
//bootstrap the app
angular.element(function () {
angular.bootstrap(document, ["app"]);
});
webpack.config.js in [email protected]
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
const path = require("path");
module.exports = {
//create entry point for the application
entry: "./index.js",
output: {
filename: "bundle.js",
path: path.resolve(__dirname, "dist"),
publicPath: "/"
},
stats: {
children: true
},
mode: "development",
module: {
rules: [
{
test: /\.(png|jpe?g|gif|svg)$/i,
type: "asset/resource",
generator: {
filename: "img/[name][ext]"
}
},
{
test: /\.(woff(2)?|ttf)$/,
use: [
{
loader: "file-loader",
options: {
name: "[name].[ext]",
outputPath: "fonts/",
publicPath: "/fonts/"
}
}
]
},
{
test: /\.mjs$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: "babel-loader",
options: {
presets: ["@babel/preset-env"]
}
}
},
{
test: /\.html$/,
use: [
{
loader: "html-loader",
options: { minimize: true }
}
]
}
]
},
resolve: {
extensions: [".js", ".mjs", ".json"]
},
plugins: [
new CleanWebpackPlugin(),
new CopyWebpackPlugin({
patterns: [
{ from: "app/Content/img", to: "img" },
{ from: "app/fonts", to: "fonts" },
{
from: "app/**/*.html",
to: ({ context, absoluteFilename }) => {
const relativePath = path.relative(context, absoluteFilename);
const newPath = path.join(
path.dirname(relativePath),
path.basename(absoluteFilename)
);
return newPath.startsWith("app") ? newPath.slice(4) : newPath;
},
noErrorOnMissing: true,
globOptions: { ignore: ["**/index.html"] }
}
]
}),
new HtmlWebpackPlugin({
template: "./app/index.html"
}),
new ModuleFederationPlugin({
name: "angularjs",
library: { type: "var", name: "angularjs" },
filename: "remoteEntry.js",
exposes: {
"./web-components": "./app/app.module.mjs"
},
remotes: {
// For remotes (please adjust)
angularjs: "http://localhost:4203/remoteEntry.js"
},
shared: []
})
],
devServer: {
// contentBase: path.join(__dirname, "dist"),
compress: true,
historyApiFallback: true, // this is needed for SPA routing
port: 4203,
proxy: {
"/api": {
target: "https://api-qa.abc.com",
secure: false,
changeOrigin: true
}
},
headers: {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, PATCH, OPTIONS",
"Access-Control-Allow-Headers":
"X-Requested-With, content-type, Authorization"
}
}
};
index.js // entry point in [email protected]
require("./app/app.module.mjs");

