{"id":6122,"date":"2022-05-02T00:00:00","date_gmt":"2022-05-01T22:00:00","guid":{"rendered":"https:\/\/www.angulararchitects.io\/?p=6122"},"modified":"2024-01-19T15:34:42","modified_gmt":"2024-01-19T14:34:42","slug":"multi-framework-and-version-micro-frontends-with-module-federation-your-4-steps-guide","status":"publish","type":"post","link":"https:\/\/www.angulararchitects.io\/en\/blog\/multi-framework-and-version-micro-frontends-with-module-federation-your-4-steps-guide\/","title":{"rendered":"Multi-Framework and -Version Micro Frontends with Module Federation: Your 4 Steps Guide"},"content":{"rendered":"<div class=\"wp-post-series-box series-module-federation wp-post-series-box--expandable\">\n\t\t\t<input id=\"collapsible-series-module-federation6a2ff3917cc3d\" class=\"wp-post-series-box__toggle_checkbox\" type=\"checkbox\">\n\t\n\t<label\n\t\tclass=\"wp-post-series-box__label\"\n\t\t\t\t\tfor=\"collapsible-series-module-federation6a2ff3917cc3d\"\n\t\t\ttabindex=\"0\"\n\t\t\t\t>\n\t\t<p class=\"wp-post-series-box__name wp-post-series-name\">\n\t\t\tThis is post 8 of 10 in the series <em>&ldquo;Module Federation&rdquo;<\/em>\t\t<\/p>\n\t\t\t<\/label>\n\n\t\t\t<div class=\"wp-post-series-box__posts\">\n\t\t\t<ol>\n\t\t\t\t\t\t\t\t\t<li><a href=\"https:\/\/www.angulararchitects.io\/en\/blog\/the-microfrontend-revolution-module-federation-in-webpack-5\/\">The Microfrontend Revolution: Module Federation in Webpack 5<\/a><\/li>\n\t\t\t\t\t\t\t\t\t<li><a href=\"https:\/\/www.angulararchitects.io\/en\/blog\/the-microfrontend-revolution-part-2-module-federation-with-angular\/\">The Microfrontend Revolution: Module Federation with Angular<\/a><\/li>\n\t\t\t\t\t\t\t\t\t<li><a href=\"https:\/\/www.angulararchitects.io\/en\/blog\/dynamic-module-federation-with-angular\/\">Dynamic Module Federation with Angular<\/a><\/li>\n\t\t\t\t\t\t\t\t\t<li><a href=\"https:\/\/www.angulararchitects.io\/en\/blog\/dynamic-module-federation-with-angular-2\/\">Building A Plugin-based Workflow Designer With Angular and Module Federation<\/a><\/li>\n\t\t\t\t\t\t\t\t\t<li><a href=\"https:\/\/www.angulararchitects.io\/en\/blog\/getting-out-of-version-mismatch-hell-with-module-federation\/\">Getting Out of Version-Mismatch-Hell with Module Federation<\/a><\/li>\n\t\t\t\t\t\t\t\t\t<li><a href=\"https:\/\/www.angulararchitects.io\/en\/blog\/using-module-federation-with-monorepos-and-angular\/\">Using Module Federation with (Nx) Monorepos and Angular<\/a><\/li>\n\t\t\t\t\t\t\t\t\t<li><a href=\"https:\/\/www.angulararchitects.io\/en\/blog\/pitfalls-with-module-federation-and-angular\/\">Pitfalls with Module Federation and Angular<\/a><\/li>\n\t\t\t\t\t\t\t\t\t<li><span class=\"wp-post-series-box__current\">Multi-Framework and -Version Micro Frontends with Module Federation: Your 4 Steps Guide<\/span><\/li>\n\t\t\t\t\t\t\t\t\t<li><a href=\"https:\/\/www.angulararchitects.io\/en\/blog\/module-federation-with-angulars-standalone-components\/\">Module Federation with Angular&#8217;s Standalone Components<\/a><\/li>\n\t\t\t\t\t\t\t\t\t<li><a href=\"https:\/\/www.angulararchitects.io\/en\/blog\/whats-new-in-angular-architects-module-federation-14-3\/\">What&#8217;s New in our Module Federation Plugin 14.3?<\/a><\/li>\n\t\t\t\t\t\t\t<\/ol>\n\t\t<\/div>\n\t<\/div>\n<p>Most articles on Module Federation assume, you have just one version of your major Framework, e. g. Angular. However, what to do if you have to mix and match different versions or different frameworks? No worries, we got you covered. This article uses an example to explain how to develop such a scenario in 4 steps. <\/p>\n<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2022\/04\/example.gif\" alt=\"Example\" \/><\/p>\n<p>Please find the live demo and the source code here:<\/p>\n<ul>\n<li><a href=\"https:\/\/red-ocean-0fe4c4610.azurestaticapps.net\">Live Example<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/manfredsteyer\/multi-framework-version\">Source Code Shell<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/manfredsteyer\/angular-app1\">Source Code for Micro Frontend<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/manfredsteyer\/angular3-app\">Source Code for Micro Frontend with Routing<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/manfredsteyer\/vue-js\">Source Code for Micro Frontend with Vue<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/manfredsteyer\/react-app\">Source Code for Micro Frontend with React<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/manfredsteyer\/angularjs-app\">Source Code for Micro Frontend with AngularJS<\/a><\/li>\n<\/ul>\n<h2>Pattern or Anti-Pattern?<\/h2>\n<p>In his recent talk on <a href=\"https:\/\/www.youtube.com\/watch?v=asXPRrg6M2Y\">Micro Frontend Anti Patterns<\/a>, my friend <a href=\"https:\/\/twitter.com\/lucamezzalira\">Luca Mezzalira<\/a> mentions using several frontend frameworks in one application. He calls this anti pattern the <a href=\"https:\/\/en.wikipedia.org\/wiki\/Lernaean_Hydra\">Hydra of Lerna<\/a>. This name comes from a water monster in Greek and Roman mythology having several heads. <\/p>\n<p>There's a good reason for considering this an anti pattern: Current frameworks are not prepared to be bootstrapped in the same browser tab together with other frameworks or other versions of themselves. Besides leading to bigger bundles, this also increases the complexity and calls for some workarounds.  <\/p>\n<p>However, Luca also explains that there are some situations where such an approach <strong>might be needed<\/strong>. He brings up the following examples:<\/p>\n<ol>\n<li>Dealing with legacy systems<\/li>\n<li>Migration to a new UI framework\/ library<\/li>\n<li>After merging companies with different tech stacks<\/li>\n<\/ol>\n<p>This all speaks right from my heart and perfectly correlates with my &quot;story&quot; I'm telling a lot at conferences and at our company workshops: Try to avoid mixing frameworks and versions in the browser. However, if you have a good reason for doing it after ruling out the alternatives, there are ways for making Multi-Framework\/ Multi-Version Micro Frontends work.<\/p>\n<p>As always in the area of software architecture -- and probably in life as general -- it's all about <strong>trade-offs<\/strong>. So if you find out that this approach comes with less drawbacks than alternatives with respect to your very <strong>architecture goals<\/strong>, lets go for it.<\/p>\n<h2>Micro Frontends as Web Components?<\/h2>\n<p>While not 100% necessary, it can be a good idea to wrap your Micro Frontends in Web Components.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2022\/04\/wrapping-wc.png\" alt=\"Micro Frontends wrapped in Web Components\" \/><\/p>\n<p>This brings several advantages:<\/p>\n<ul>\n<li>Abstracting differences between frameworks<\/li>\n<li>Mounting\/ Unmounting Web Components is easy<\/li>\n<li>Shadow DOM helps with isolating CSS styles<\/li>\n<li>Custom Events and Properties allow to communicate<\/li>\n<\/ul>\n<p>The first two options correlate with each other. We need to display and hide our Micro Frontends on demand, e. g. when activating a specific menu item. As each Micro Frontend is a self-contained frontend, this also means we have to bootstrap it on demand in the middle of our page. For this, different frameworks provide different methods or functions. When wrapped into Web Components, all we need to do is to add or remove the respective HTML element registered with the Web Component.<\/p>\n<p>Isolating CSS styles via Shadow DOM helps to make teams more self-sufficient. However, I've seen that quite often teams trade in a bit of independence for some global CSS rules provided by the shell. In this case, the Shadow DOM emulation provided by Angular (with and without Web Components) is a good choice: While it prevents styles from other components bleeding into yours, it allows to share global styles too. <\/p>\n<p>Also, Custom Events and Properties seem to be a good choice for communicating at first glance. However, for the sake of simplicity, meanwhile, I prefer a simple object acting as a mediator or &quot;mini message bus&quot; in the global namespace.<\/p>\n<p>In general, we have to see that such Web Components wrapping whole Micro Frontends are no typical Web Components. I'm stressing this out because sometimes people confuse the idea of a (Web) Component with the idea of a Micro Frontend or use these terms synonymously. This leads to far too fine-grained Micro Frontends causing lots of issues with integration. <\/p>\n<h2>Do we also need Module Federation?<\/h2>\n<p>Module Federation makes it easy to load parts of other applications into a host. In our case, the host is the Micro Frontend shell. Also, Module Federation allows for sharing libraries between the shell and the micro frontends. <\/p>\n<p>It even comes with several strategies for dealing with versions mismatches. For instance, we could configure it to reuse an existing library if the versions match exactly. Otherwise, we could instruct it to load the version is has been built with. <\/p>\n<p>Loading the discussed Micro Frontends with Module Federation hence gives us the best of both worlds. We can share libraries when possible and load our own when not:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2020\/12\/venn.png\" alt=\"The Best of Both Worlds\" \/><\/p>\n<h2>Implementation in 4 Steps<\/h2>\n<p>Now, after discussing the implementation strategy, let's look at the promised 4 steps for building such a solution.<\/p>\n<h3>Step 1: Wrap your Micro Frontend in a Web Component<\/h3>\n<p>For wrapping Angular-based Micro Frontends in a Web Component, you can go with Angular Elements provided by the Angular team. Install it via npm:<\/p>\n<pre><code class=\"language-bash\">npm i @angular\/elements<\/code><\/pre>\n<p>After installing it, adjust your <code>AppModule<\/code> as follows:<\/p>\n<pre><code class=\"language-typescript\"> import { createCustomElement } from &#039;@angular\/elements&#039;;\n [...]\n\n @NgModule({\n   [...]\n   declarations: [\n     AppComponent\n   ],\n   bootstrap: [] \/\/ No bootstrap components!\n })\n export class AppModule implements DoBoostrap {\n   constructor(private injector: Injector) {\n   }\n\n   ngDoBootstrap() {\n     const ce = createCustomElement(AppComponent, {injector: this.injector});\n     customElements.define(&#039;angular1-element&#039;, ce);\n   }\n\n }<\/code><\/pre>\n<p>This does several things:<\/p>\n<ul>\n<li>By going with an empty bootstrap array, Angular won't directly bootstrap any component on startup. However, in such cases, Angular demands us of placing a custom bootstrap logic in the method <code>ngDoBootstrap<\/code> described by the <code>DoBoostrap<\/code> interface.<\/li>\n<li><code>ngDoBootstrap<\/code> uses Angular Elements' <code>createCustomElement<\/code> to wrap your <code>AppComponent<\/code> in a Web Component. To make it work with DI, you also need to pass the current <code>Injector<\/code>.<\/li>\n<li>The method <code>customElements.define<\/code> registers the Web Component under the name <code>angular1-element<\/code> with the browser. <\/li>\n<\/ul>\n<p>The result of this is that the browser will mount the Application in every <code>angular1-element<\/code> tag that occurs in your application.<\/p>\n<p>If your framework doesn't directly support web components, you can also hand-wrap your application. For instance, a React component could be wrapped as follows:<\/p>\n<pre><code class=\"language-typescript\"> \/\/ app.js\n import React from &#039;react&#039;\n import ReactDOM from &#039;react-dom&#039;\n\n class App extends React.Component {\n\n   render() {\n     const reactVersion = require(&#039;.\/package.json&#039;).dependencies[&#039;react&#039;];\n\n     return ([\n         &lt;h1&gt;\n           React\n         &lt;\/h1&gt;,\n         &lt;p&gt;\n           React Version: {reactVersion}\n         &lt;\/p&gt;\n     ])\n   }\n }\n\n class Mfe4Element extends HTMLElement {\n   connectedCallback() {\n     ReactDOM.render(&lt;App\/&gt;, this);\n   }\n }\n\n customElements.define(&#039;react-element&#039;, Mfe4Element);<\/code><\/pre>\n<h3>Step 2: Expose your Web Component via Module Federation<\/h3>\n<p>To be able to load the Micro Frontends into the shell, we need to expose the Web Components wrapping them via Module Federation. For this, add the package @angular-architects\/module-federation to your Angular-based Micro Frontend:<\/p>\n<pre><code class=\"language-bash\">ng add @angular-architects\/module-federation<\/code><\/pre>\n<p>This installs and initializes the package. If you go with Nx and Angular, its more usual to do both steps separately:<\/p>\n<pre><code class=\"language-bash\"> npm i @angular-architects\/module-federation -D\n ng g @angular-architects\/module-federation:init <\/code><\/pre>\n<p>In the case of other frameworks like React or Vue, this all is just about adding the <code>ModuleFederationPlugin<\/code> to the webpack configuration. Please remember that you need to bootstrap your application asynchronously in most cases. Hence, your entry file will more or less just contain a dynamic <code>import<\/code> loading the rest of the application. <\/p>\n<p>For this reason, the above discussed React-based Micro Frontend uses the following <code>index.js<\/code> as the entry point:<\/p>\n<pre><code class=\"language-typescript\"> \/\/ index.js\n import(&#039;.\/app&#039;);<\/code><\/pre>\n<p>Similarly, @angular-architects\/module-federation is moving the bootstrap code from <code>main.ts<\/code> into a newly created <code>bootstrap.ts<\/code> and imports it:<\/p>\n<pre><code class=\"language-typescript\">\/\/ main.ts\n import(&#039;.\/bootstrap&#039;);<\/code><\/pre>\n<p>This common pattern gives Module Federation the necessary time for loading the shared dependencies.<\/p>\n<p>After setting up Module Federation, expose the Web Component-based wrapper via the webpack configuration:<\/p>\n<pre><code class=\"language-typescript\"> \/\/ webpack.config.js\n [...]\n module.exports = {\n   [...]\n   plugins: [\n     new ModuleFederationPlugin({\n\n       name: &quot;angular1&quot;,\n       filename: &quot;remoteEntry.js&quot;,\n\n       exposes: {\n         &#039;.\/web-components&#039;: &#039;.\/src\/bootstrap.ts&#039;,\n       },\n\n       shared: share({\n         &quot;@angular\/core&quot;: { requiredVersion: &quot;auto&quot; },\n         &quot;@angular\/common&quot;: { requiredVersion: &quot;auto&quot; },\n         &quot;@angular\/router&quot;: { requiredVersion: &quot;auto&quot; },\n         &quot;rxjs&quot;: { requiredVersion: &quot;auto&quot; },\n\n         ...sharedMappings.getDescriptors()\n       }),\n       [...]\n     })\n   ],\n };<\/code><\/pre>\n<blockquote>\n<p>As the goal is to show how to mix different versions of Angular, this Micro Frontend uses Angular 12 while the shell shown below uses a more recent Angular version. Hence, also an older version of @angular-architects\/module-federation and the original more verbose configuration is used. Please find <a href=\"https:\/\/github.com\/angular-architects\/module-federation-plugin\/blob\/main\/migration-guide.md\">details on different versions<\/a> here.<\/p>\n<\/blockquote>\n<p>The settings in the section <code>shared<\/code> make sure we can mix several versions of a framework but also reuse an already loaded one if the version numbers fit exactly. For this, <code>requiredVersion<\/code> should point to the installed version -- the one, you also find in your <code>package.json<\/code>. The helper method <code>share<\/code> that comes with @angular-architects\/module-federation takes care of this when setting <code>requiredVersion<\/code> to <code>auto<\/code>.<\/p>\n<blockquote>\n<p>While according to semantic versioning an Angular library with a higher minor or patch version is backwards compatible, there are no such guarantees for already compiled code. The reason is that the code emitted by the Angular compiler uses Angular's internal APIs semantic does not apply for. Hence, you should use an exact version number (without any <code>^<\/code> or <code>~<\/code>).<\/p>\n<\/blockquote>\n<h3>Step 3: Perform Workaround for Angular<\/h3>\n<p>To make several Angular application work together in one browser window, we need <a href=\"https:\/\/www.angulararchitects.io\/aktuelles\/multi-framework-and-version-micro-frontends-with-module-federation-the-good-the-bad-the-ugly\/\">some workarounds<\/a>. The good message is, we've implemented them in a very slim add-on to @angular-architects\/module-federation called <a href=\"https:\/\/www.npmjs.com\/package\/@angular-architects\/module-federation-tools\">@angular-architects\/module-federation-tools<\/a>. <\/p>\n<p>Just install it (<code>npm i @angular-architects\/module-federation-tools -D<\/code>) into <strong>both, your Micro Frontends and your shell<\/strong>. Then, bootstrap your shell and your Micro Frontends with its <code>bootstrap<\/code> method instead of with Angular's one:<\/p>\n<pre><code class=\"language-typescript\"> \/\/ main.ts\n import { AppModule } from &#039;.\/app\/app.module&#039;;\n import { environment } from &#039;.\/environments\/environment&#039;;\n import { bootstrap } from &#039;@angular-architects\/module-federation-tools&#039;;\n\n bootstrap(AppModule, {\n   production: environment.production,\n   appType: &#039;microfrontend&#039;  \/\/ for micro frontend\n   \/\/ appType: &#039;shell&#039;,      \/\/ for shell\n });<\/code><\/pre>\n<h3>Step 4: Load Micro Frontends into the Shell<\/h3>\n<p>Also, enable Module Federation in your shell. If it is an Angular-based shell, add the @angular-architects\/module-federation plugin:<\/p>\n<pre><code class=\"language-bash\">ng add @angular-architects\/module-federation<\/code><\/pre>\n<p>As mentioned above, in the case of Nx and Angular, perform the installation and initialization separately:<\/p>\n<pre><code class=\"language-bash\">npm i @angular-architects\/module-federation -D\n ng g @angular-architects\/module-federation:init --type host<\/code><\/pre>\n<blockquote>\n<p>The switch --type host generates a typical host configuration. It is available since plugin version 14.3 and hence since Angular 14.<\/p>\n<\/blockquote>\n<p>For this example, we don't need to adjust the generated <code><code>webpack.config.js<\/code><\/code>:<\/p>\n<pre><code class=\"language-typescript\"> \/\/ webpack.config.js\n const { shareAll, withModuleFederationPlugin } = require(&#039;@angular-architects\/module-federation\/webpack&#039;);\n\n module.exports = withModuleFederationPlugin({\n\n     shared: {\n         ...shareAll({ singleton: true, strictVersion: true, requiredVersion: &#039;auto&#039; }),\n     },\n\n });<\/code><\/pre>\n<p>Other settings provided by the <code>ModuleFederationPlugin<\/code> aren't needed here. <\/p>\n<p>After this, all you need is a lazy route, loading the Micro Frontends in question:<\/p>\n<pre><code class=\"language-javascript\"> import { WebComponentWrapper, WebComponentWrapperOptions } from &#039;@angular-architects\/module-federation-tools&#039;;\n\n export const APP_ROUTES: Routes = [\n     [...]\n     {\n         path: &#039;react&#039;,\n         component: WebComponentWrapper,\n         data: {\n             remoteEntry: &#039;https:\/\/witty-wave-0a695f710.azurestaticapps.net\/remoteEntry.js&#039;,\n             remoteName: &#039;react&#039;,\n             exposedModule: &#039;.\/web-components&#039;,\n\n             elementName: &#039;react-element&#039;\n         } as WebComponentWrapperOptions\n     },\n     [...]\n ]<\/code><\/pre>\n<p>The <code>WebComponentWrapper<\/code> used here is provided by @angular-architects\/module-federation-tools. It just loads the Web Component via Module Federation using the given key data. In the shown case, this react application is deployed as an Azure Static Web App. The values for <code>remoteName<\/code> and <code>exposedModule<\/code> can be found in the Micro Frontend's webpack configuration.<\/p>\n<p>The wrapper component also creates an HTML element with the name <code>react-element<\/code> the Web Component is mounted in.<\/p>\n<p>If you load a Micro Frontend compiled with Angular 13 or higher, you need to set the property <code>type<\/code> to <code>module<\/code>:<\/p>\n<pre><code class=\"language-typescript\"> export const APP_ROUTES: Routes = [\n     [...]\n     {\n         path: &#039;angular1&#039;,\n         component: WebComponentWrapper,\n         data: {\n           type: &#039;module&#039;,\n           remoteEntry: &#039;https:\/\/your-path\/remoteEntry.js&#039;,\n           exposedModule: &#039;.\/web-components&#039;,\n\n           elementName: &#039;angular1-element&#039;\n         } as WebComponentWrapperOptions\n     },\n     [...]\n }<\/code><\/pre>\n<p>Also, in the case of Angular 13+ you don't need the <code>remoteName<\/code> property. The reason for these two differences is that Angular CLI 13+ don't emit &quot;old-style JavaScript&quot; files anymore but JavaScript modules. Their handling in Module Federation is a bit different.<\/p>\n<p>If your Micro Frontend brings its own router, you need to tell your shell that the Micro Frontend will append further segments to the URL. For this, you can go with the <code>startsWith<\/code> matcher also provided by @angular-architects\/module-federation-tools:<\/p>\n<pre><code class=\"language-typescript\"> import { \n     startsWith, \n     WebComponentWrapper, \n     WebComponentWrapperOptions \n } \n from &#039;@angular-architects\/module-federation-tools&#039;;\n\n [...]\n\n export const APP_ROUTES: Routes = [\n     [...]\n     {\n         matcher: startsWith(&#039;angular3&#039;),\n         component: WebComponentWrapper,\n         data: {\n             [...]\n         } as WebComponentWrapperOptions\n     },\n     [...]\n }<\/code><\/pre>\n<p>To make this work, the path prefix <code>angular3<\/code> used here needs to be used by the Micro Frontend too. As the routing config is just a data structure, you will find ways to add it dynamically. <\/p>\n<h3>Result<\/h3>\n<p>The result of this endeavor is an application that consists of different frameworks respective framework-versions:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2022\/04\/example.gif\" alt=\"Example\" \/><\/p>\n<p>Whenever possible, the framework is shared. Otherwise, a new framework (version) is loaded by Module Federation. Another advantage of this approach is that it works without any additional meta framework. We just need some thin helper functions. <\/p>\n<p>The drawbacks are increased complexity and bundle sizes. Also, we are leaving the path of the supported use cases: None of the frameworks has been officially tested together with other frameworks or other versions of itself in the same browser tab.<\/p>\n<h2>What's next? More on Architecture!<\/h2>\n<p>So far, we've seen how to decompose a huge client into several Micro Frontends that can even use different frameworks. However, when dealing with enterprise-scale frontends, several additional questions come in mind:<\/p>\n<ul>\n<li>According to which criteria can we subdivide a huge application into sub-domains?<\/li>\n<li>How can we enforce loosely coupling?<\/li>\n<li>How can we make sure, the solution is maintainable for years or even decades?<\/li>\n<li>Which proven patterns should we use?<\/li>\n<li>Which other options from Micro Frontends are provided by Module Federation?<\/li>\n<li>Shall we go with a monorepo or with multiple ones?<\/li>\n<\/ul>\n<p>Our free eBook (about 120 pages) covers all these questions and more:<\/p>\n<p><a href=\"https:\/\/www.angulararchitects.io\/book\"><img decoding=\"async\" src=\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2020\/12\/cover-small.png\" alt=\"free ebook\"><\/a><\/p>\n<p>Feel free to <a href=\"https:\/\/www.angulararchitects.io\/book\">download it here<\/a> now!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This article shows an approach for using different frameworks and versions together. It also discusses the pros and cons.<\/p>\n","protected":false},"author":9,"featured_media":6118,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_price":"","_stock":"","_tribe_ticket_header":"","_tribe_default_ticket_provider":"","_ticket_start_date":"","_ticket_end_date":"","_tribe_ticket_show_description":"","_tribe_ticket_show_not_going":false,"_tribe_ticket_use_global_stock":"","_tribe_ticket_global_stock_level":"","_global_stock_mode":"","_global_stock_cap":"","_tribe_rsvp_for_event":"","_tribe_ticket_going_count":"","_tribe_ticket_not_going_count":"","_tribe_tickets_list":"[]","_tribe_ticket_has_attendee_info_fields":false,"footnotes":""},"categories":[18],"tags":[],"class_list":["post-6122","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized","post_series-module-federation"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.1.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Multi-Framework and -Version Micro Frontends with Module Federation: Your 4 Steps Guide - ANGULARarchitects<\/title>\n<meta name=\"description\" content=\"This articles discusses an approach for using several frameworks and versions togehter. It also outlines the pros and cons.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.angulararchitects.io\/en\/blog\/multi-framework-and-version-micro-frontends-with-module-federation-your-4-steps-guide\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Multi-Framework and -Version Micro Frontends with Module Federation: Your 4 Steps Guide - ANGULARarchitects\" \/>\n<meta property=\"og:description\" content=\"This articles discusses an approach for using several frameworks and versions togehter. It also outlines the pros and cons.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.angulararchitects.io\/en\/blog\/multi-framework-and-version-micro-frontends-with-module-federation-your-4-steps-guide\/\" \/>\n<meta property=\"og:site_name\" content=\"ANGULARarchitects\" \/>\n<meta property=\"article:published_time\" content=\"2022-05-01T22:00:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-01-19T14:34:42+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2022\/04\/social.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"800\" \/>\n\t<meta property=\"og:image:height\" content=\"418\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Manfred Steyer, GDE\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@daniel\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Manfred Steyer, GDE\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"11 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/multi-framework-and-version-micro-frontends-with-module-federation-your-4-steps-guide\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/multi-framework-and-version-micro-frontends-with-module-federation-your-4-steps-guide\/\"},\"author\":{\"name\":\"Manfred Steyer, GDE\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/15628efa7af4475ffaaeeb26c5112951\"},\"headline\":\"Multi-Framework and -Version Micro Frontends with Module Federation: Your 4 Steps Guide\",\"datePublished\":\"2022-05-01T22:00:00+00:00\",\"dateModified\":\"2024-01-19T14:34:42+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/multi-framework-and-version-micro-frontends-with-module-federation-your-4-steps-guide\/\"},\"wordCount\":1879,\"publisher\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/multi-framework-and-version-micro-frontends-with-module-federation-your-4-steps-guide\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2022\/04\/bg.jpg\",\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/multi-framework-and-version-micro-frontends-with-module-federation-your-4-steps-guide\/\",\"url\":\"https:\/\/www.angulararchitects.io\/en\/blog\/multi-framework-and-version-micro-frontends-with-module-federation-your-4-steps-guide\/\",\"name\":\"Multi-Framework and -Version Micro Frontends with Module Federation: Your 4 Steps Guide - ANGULARarchitects\",\"isPartOf\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/multi-framework-and-version-micro-frontends-with-module-federation-your-4-steps-guide\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/multi-framework-and-version-micro-frontends-with-module-federation-your-4-steps-guide\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2022\/04\/bg.jpg\",\"datePublished\":\"2022-05-01T22:00:00+00:00\",\"dateModified\":\"2024-01-19T14:34:42+00:00\",\"description\":\"This articles discusses an approach for using several frameworks and versions togehter. It also outlines the pros and cons.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/multi-framework-and-version-micro-frontends-with-module-federation-your-4-steps-guide\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.angulararchitects.io\/en\/blog\/multi-framework-and-version-micro-frontends-with-module-federation-your-4-steps-guide\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/multi-framework-and-version-micro-frontends-with-module-federation-your-4-steps-guide\/#primaryimage\",\"url\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2022\/04\/bg.jpg\",\"contentUrl\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2022\/04\/bg.jpg\",\"width\":2000,\"height\":1009},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/multi-framework-and-version-micro-frontends-with-module-federation-your-4-steps-guide\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.angulararchitects.io\/en\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Multi-Framework and -Version Micro Frontends with Module Federation: Your 4 Steps Guide\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#website\",\"url\":\"https:\/\/www.angulararchitects.io\/en\/\",\"name\":\"ANGULARarchitects\",\"description\":\"AngularArchitects.io\",\"publisher\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.angulararchitects.io\/en\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#organization\",\"name\":\"ANGULARarchitects\",\"alternateName\":\"SOFTWAREarchitects\",\"url\":\"https:\/\/www.angulararchitects.io\/en\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2023\/07\/AA-Logo-RGB-horizontal-inside-knowledge-black.svg\",\"contentUrl\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2023\/07\/AA-Logo-RGB-horizontal-inside-knowledge-black.svg\",\"width\":644,\"height\":216,\"caption\":\"ANGULARarchitects\"},\"image\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/github.com\/angular-architects\",\"https:\/\/www.linkedin.com\/company\/angular-architects\/\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/15628efa7af4475ffaaeeb26c5112951\",\"name\":\"Manfred Steyer, GDE\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/a0b59539674d8b71ea1c1f4764b11244b5f499203f1d11b40f37d8f3f90be033?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/a0b59539674d8b71ea1c1f4764b11244b5f499203f1d11b40f37d8f3f90be033?s=96&d=mm&r=g\",\"caption\":\"Manfred Steyer, GDE\"},\"sameAs\":[\"https:\/\/x.com\/daniel\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Multi-Framework and -Version Micro Frontends with Module Federation: Your 4 Steps Guide - ANGULARarchitects","description":"This articles discusses an approach for using several frameworks and versions togehter. It also outlines the pros and cons.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.angulararchitects.io\/en\/blog\/multi-framework-and-version-micro-frontends-with-module-federation-your-4-steps-guide\/","og_locale":"en_US","og_type":"article","og_title":"Multi-Framework and -Version Micro Frontends with Module Federation: Your 4 Steps Guide - ANGULARarchitects","og_description":"This articles discusses an approach for using several frameworks and versions togehter. It also outlines the pros and cons.","og_url":"https:\/\/www.angulararchitects.io\/en\/blog\/multi-framework-and-version-micro-frontends-with-module-federation-your-4-steps-guide\/","og_site_name":"ANGULARarchitects","article_published_time":"2022-05-01T22:00:00+00:00","article_modified_time":"2024-01-19T14:34:42+00:00","og_image":[{"width":800,"height":418,"url":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2022\/04\/social.jpg","type":"image\/jpeg"}],"author":"Manfred Steyer, GDE","twitter_card":"summary_large_image","twitter_creator":"@daniel","twitter_misc":{"Written by":"Manfred Steyer, GDE","Est. reading time":"11 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.angulararchitects.io\/en\/blog\/multi-framework-and-version-micro-frontends-with-module-federation-your-4-steps-guide\/#article","isPartOf":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/multi-framework-and-version-micro-frontends-with-module-federation-your-4-steps-guide\/"},"author":{"name":"Manfred Steyer, GDE","@id":"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/15628efa7af4475ffaaeeb26c5112951"},"headline":"Multi-Framework and -Version Micro Frontends with Module Federation: Your 4 Steps Guide","datePublished":"2022-05-01T22:00:00+00:00","dateModified":"2024-01-19T14:34:42+00:00","mainEntityOfPage":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/multi-framework-and-version-micro-frontends-with-module-federation-your-4-steps-guide\/"},"wordCount":1879,"publisher":{"@id":"https:\/\/www.angulararchitects.io\/en\/#organization"},"image":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/multi-framework-and-version-micro-frontends-with-module-federation-your-4-steps-guide\/#primaryimage"},"thumbnailUrl":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2022\/04\/bg.jpg","inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/www.angulararchitects.io\/en\/blog\/multi-framework-and-version-micro-frontends-with-module-federation-your-4-steps-guide\/","url":"https:\/\/www.angulararchitects.io\/en\/blog\/multi-framework-and-version-micro-frontends-with-module-federation-your-4-steps-guide\/","name":"Multi-Framework and -Version Micro Frontends with Module Federation: Your 4 Steps Guide - ANGULARarchitects","isPartOf":{"@id":"https:\/\/www.angulararchitects.io\/en\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/multi-framework-and-version-micro-frontends-with-module-federation-your-4-steps-guide\/#primaryimage"},"image":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/multi-framework-and-version-micro-frontends-with-module-federation-your-4-steps-guide\/#primaryimage"},"thumbnailUrl":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2022\/04\/bg.jpg","datePublished":"2022-05-01T22:00:00+00:00","dateModified":"2024-01-19T14:34:42+00:00","description":"This articles discusses an approach for using several frameworks and versions togehter. It also outlines the pros and cons.","breadcrumb":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/multi-framework-and-version-micro-frontends-with-module-federation-your-4-steps-guide\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.angulararchitects.io\/en\/blog\/multi-framework-and-version-micro-frontends-with-module-federation-your-4-steps-guide\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.angulararchitects.io\/en\/blog\/multi-framework-and-version-micro-frontends-with-module-federation-your-4-steps-guide\/#primaryimage","url":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2022\/04\/bg.jpg","contentUrl":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2022\/04\/bg.jpg","width":2000,"height":1009},{"@type":"BreadcrumbList","@id":"https:\/\/www.angulararchitects.io\/en\/blog\/multi-framework-and-version-micro-frontends-with-module-federation-your-4-steps-guide\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.angulararchitects.io\/en\/"},{"@type":"ListItem","position":2,"name":"Multi-Framework and -Version Micro Frontends with Module Federation: Your 4 Steps Guide"}]},{"@type":"WebSite","@id":"https:\/\/www.angulararchitects.io\/en\/#website","url":"https:\/\/www.angulararchitects.io\/en\/","name":"ANGULARarchitects","description":"AngularArchitects.io","publisher":{"@id":"https:\/\/www.angulararchitects.io\/en\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.angulararchitects.io\/en\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.angulararchitects.io\/en\/#organization","name":"ANGULARarchitects","alternateName":"SOFTWAREarchitects","url":"https:\/\/www.angulararchitects.io\/en\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.angulararchitects.io\/en\/#\/schema\/logo\/image\/","url":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2023\/07\/AA-Logo-RGB-horizontal-inside-knowledge-black.svg","contentUrl":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2023\/07\/AA-Logo-RGB-horizontal-inside-knowledge-black.svg","width":644,"height":216,"caption":"ANGULARarchitects"},"image":{"@id":"https:\/\/www.angulararchitects.io\/en\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/github.com\/angular-architects","https:\/\/www.linkedin.com\/company\/angular-architects\/"]},{"@type":"Person","@id":"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/15628efa7af4475ffaaeeb26c5112951","name":"Manfred Steyer, GDE","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/a0b59539674d8b71ea1c1f4764b11244b5f499203f1d11b40f37d8f3f90be033?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/a0b59539674d8b71ea1c1f4764b11244b5f499203f1d11b40f37d8f3f90be033?s=96&d=mm&r=g","caption":"Manfred Steyer, GDE"},"sameAs":["https:\/\/x.com\/daniel"]}]}},"_links":{"self":[{"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/posts\/6122","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/users\/9"}],"replies":[{"embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/comments?post=6122"}],"version-history":[{"count":9,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/posts\/6122\/revisions"}],"predecessor-version":[{"id":24271,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/posts\/6122\/revisions\/24271"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/media\/6118"}],"wp:attachment":[{"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/media?parent=6122"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/categories?post=6122"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/tags?post=6122"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}