{"id":7067,"date":"2025-06-20T13:32:44","date_gmt":"2025-06-20T13:32:44","guid":{"rendered":"https:\/\/namastedev.com\/blog\/?p=7067"},"modified":"2025-06-20T13:32:44","modified_gmt":"2025-06-20T13:32:44","slug":"creating-micro-frontends-with-react-3","status":"publish","type":"post","link":"https:\/\/namastedev.com\/blog\/creating-micro-frontends-with-react-3\/","title":{"rendered":"Creating Micro Frontends with React"},"content":{"rendered":"<h1>Creating Micro Frontends with React: A Comprehensive Guide<\/h1>\n<p>In recent years, the concept of micro frontends has emerged as a powerful architectural style for building scalable, maintainable web applications. By enabling teams to work independently on different parts of an application, micro frontends facilitate parallel development and improve the overall agility of software delivery. This article explores how to create micro frontends using React, a popular JavaScript library for building user interfaces.<\/p>\n<h2>What are Micro Frontends?<\/h2>\n<p>Micro frontends break a monolithic front-end application into smaller, manageable, and independently deployable pieces. Each piece represents a specific business domain or feature and can be developed, tested, and deployed by different teams. This allows for:<\/p>\n<ul>\n<li><strong>Independent Development:<\/strong> Teams can work on their own features without waiting for others.<\/li>\n<li><strong>Technology Agnostic:<\/strong> Different parts of the application can be built with different technologies.<\/li>\n<li><strong>Scalability:<\/strong> The overall system can grow more easily as the application matures.<\/li>\n<\/ul>\n<p>By leveraging micro frontends, organizations can adapt to changing requirements and scale their web applications more effectively.<\/p>\n<h2>Key Concepts in Micro Frontend Architecture<\/h2>\n<p>Before diving into the implementation, let\u2019s review some key concepts associated with micro frontends:<\/p>\n<ul>\n<li><strong>Single SPA:<\/strong> A framework for managing multiple micro frontends on one page.<\/li>\n<li><strong>Module Federation:<\/strong> A Webpack 5 feature that allows dynamic code sharing between applications.<\/li>\n<li><strong>Routing and Navigation:<\/strong> Effective strategies to handle routing across different micro frontends.<\/li>\n<li><strong>Communication:<\/strong> Mechanisms to enable communication between micro frontends.<\/li>\n<\/ul>\n<h2>Setting Up Your Micro Frontend Environment<\/h2>\n<p>We&#8217;ll use <strong>React<\/strong> with <strong>Single SPA<\/strong> and <strong>Webpack Module Federation<\/strong> for our micro frontend setup. Begin by creating a new directory for our project:<\/p>\n<pre><code>mkdir react-micro-frontends\ncd react-micro-frontends\n<\/code><\/pre>\n<p>Next, initialize a new npm project:<\/p>\n<pre><code>npm init -y\n<\/code><\/pre>\n<p>Install necessary dependencies:<\/p>\n<pre><code>npm install react react-dom single-spa\nnpm install --save-dev webpack webpack-cli webpack-dev-server html-webpack-plugin\n<\/code><\/pre>\n<h2>Creating Your First Micro Frontend<\/h2>\n<h3>Step 1: Creating a Micro Frontend Application<\/h3>\n<p>In our project, we\u2019ll create two micro frontend applications, \u201capp1\u201d and \u201capp2,\u201d which can operate independently.<\/p>\n<pre><code>mkdir app1 app2\n<\/code><\/pre>\n<p>Each application will have a standard React structure:<\/p>\n<pre><code>\napp1\/\n\u251c\u2500\u2500 src\/\n\u2502   \u251c\u2500\u2500 index.js\n\u2502   \u2514\u2500\u2500 App.js\n\u251c\u2500\u2500 public\/\n\u2502   \u2514\u2500\u2500 index.html\n\u2514\u2500\u2500 package.json\n<\/code><\/pre>\n<p>In the <strong>src\/index.js<\/strong> of app1, add:<\/p>\n<pre><code>import React from 'react';\nimport ReactDOM from 'react-dom';\nimport App from '.\/App';\n\nReactDOM.render(, document.getElementById('root'));\n<\/code><\/pre>\n<p>In the <strong>src\/App.js<\/strong>, create a simple component:<\/p>\n<pre><code>import React from 'react';\n\nconst App = () =&gt; {\n    return (\n        &lt;div&gt;\n            &lt;h1&gt;Welcome to App 1&lt;\/h1&gt;\n            &lt;p&gt;This is the first micro frontend!&lt;\/p&gt;\n        &lt;\/div&gt;\n    );\n};\n\nexport default App;\n<\/code><\/pre>\n<p>The <strong>public\/index.html<\/strong> will need to load the script generated by Webpack:<\/p>\n<pre><code>&lt;!DOCTYPE html&gt;\n&lt;html lang=\"en\"&gt;\n&lt;head&gt;\n    &lt;meta charset=\"UTF-8\"&gt;\n    &lt;meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"&gt;\n    &lt;title&gt;App 1&lt;\/title&gt;\n&lt;\/head&gt;\n&lt;body&gt;\n    &lt;div id=\"root\"&gt;&lt;\/div&gt;\n&lt;\/body&gt;\n<\/code><\/pre>\n<h3>Step 2: Configuring Webpack<\/h3>\n<p>We need to configure Webpack for each of our apps. Create a <strong>webpack.config.js<\/strong> file in the root of <strong>app1<\/strong>: <\/p>\n<pre><code>const HtmlWebpackPlugin = require('html-webpack-plugin');\nconst { ModuleFederationPlugin } = require('webpack\/lib\/container');\n\nmodule.exports = {\n    mode: 'development',\n    entry: '.\/src\/index.js',\n    output: {\n        filename: 'bundle.js',\n        publicPath: 'http:\/\/localhost:3001\/',\n    },\n    devServer: {\n        port: 3001,\n    },\n    plugins: [\n        new ModuleFederationPlugin({\n            name: 'app1',\n            filename: 'remoteEntry.js',\n            exposes: {\n                '.\/App': '.\/src\/App',\n            },\n            shared: {\n                react: {\n                    singleton: true,\n                    eager: true,\n                    requiredVersion: '^17.0.0'\n                },\n                'react-dom': {\n                    singleton: true,\n                    eager: true,\n                    requiredVersion: '^17.0.0'\n                },\n            },\n        }),\n        new HtmlWebpackPlugin({\n            template: '.\/public\/index.html'\n        }),\n    ],\n    module: {\n        rules: [\n            {\n                test: \/.jsx?$\/,\n                use: 'babel-loader',\n                exclude: \/node_modules\/,\n            },\n        ],\n    },\n};\n<\/code><\/pre>\n<p>Repeat the same for app2 while changing ports and filenames accordingly. In <strong>app2<\/strong>: <\/p>\n<pre><code>const HtmlWebpackPlugin = require('html-webpack-plugin');\nconst { ModuleFederationPlugin } = require('webpack\/lib\/container');\n\nmodule.exports = {\n    mode: 'development',\n    entry: '.\/src\/index.js',\n    output: {\n        filename: 'bundle.js',\n        publicPath: 'http:\/\/localhost:3002\/',\n    },\n    devServer: {\n        port: 3002,\n    },\n    plugins: [\n        new ModuleFederationPlugin({\n            name: 'app2',\n            filename: 'remoteEntry.js',\n            exposes: {\n                '.\/App': '.\/src\/App',\n            },\n            shared: {\n                react: {\n                    singleton: true,\n                    eager: true,\n                    requiredVersion: '^17.0.0'\n                },\n                'react-dom': {\n                    singleton: true,\n                    eager: true,\n                    requiredVersion: '^17.0.0'\n                },\n            },\n        }),\n        new HtmlWebpackPlugin({\n            template: '.\/public\/index.html'\n        }),\n    ],\n    module: {\n        rules: [\n            {\n                test: \/.jsx?$\/,\n                use: 'babel-loader',\n                exclude: \/node_modules\/,\n            },\n        ],\n    },\n};\n<\/code><\/pre>\n<h2>Step 3: Setting Up the Container Application<\/h2>\n<p>Next, we need to create a *container* application that will load our micro frontends. Create a new directory for the container:<\/p>\n<pre><code>mkdir container\ncd container\nnpm init -y\nnpm install react react-dom single-spa\nnpm install --save-dev webpack webpack-cli webpack-dev-server html-webpack-plugin\nmkdir src public\n<\/code><\/pre>\n<h3>Creating the Container Application<\/h3>\n<p>Add the following files similar to previous applications:<\/p>\n<pre><code>\ncontainer\/\n\u251c\u2500\u2500 src\/\n\u2502   \u2514\u2500\u2500 index.js\n\u251c\u2500\u2500 public\/\n\u2502   \u2514\u2500\u2500 index.html\n\u2514\u2500\u2500 webpack.config.js\n<\/code><\/pre>\n<p>In <strong>src\/index.js<\/strong>, set up Single SPA:<\/p>\n<pre><code>import { registerApplication, start } from 'single-spa';\n\nregisterApplication(\n    'app1',\n    () =&gt; import('app1\/App'),\n    () =&gt; true\n);\n\nregisterApplication(\n    'app2',\n    () =&gt; import('app2\/App'),\n    () =&gt; location.pathname === '\/app2'\n);\n\nstart();\n<\/code><\/pre>\n<p>In the <strong>public\/index.html<\/strong>, define a root element:<\/p>\n<pre><code>&lt;!DOCTYPE html&gt;\n&lt;html lang=\"en\"&gt;\n&lt;head&gt;\n    &lt;meta charset=\"UTF-8\"&gt;\n    &lt;meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"&gt;\n    &lt;title&gt;Container App&lt;\/title&gt;\n&lt;\/head&gt;\n&lt;body&gt;\n    &lt;div id=\"root\"&gt;&lt;\/div&gt;\n&lt;\/body&gt;\n<\/code><\/pre>\n<h3>Configuring Webpack for the Container<\/h3>\n<p>Create a <strong>webpack.config.js<\/strong> file in the root of the container:<\/p>\n<pre><code>const HtmlWebpackPlugin = require('html-webpack-plugin');\nconst { ModuleFederationPlugin } = require('webpack\/lib\/container');\n\nmodule.exports = {\n    mode: 'development',\n    entry: '.\/src\/index.js',\n    output: {\n        filename: 'bundle.js',\n        publicPath: 'http:\/\/localhost:3000\/',\n    },\n    devServer: {\n        port: 3000,\n    },\n    plugins: [\n        new ModuleFederationPlugin({\n            name: 'container',\n            remotes: {\n                app1: 'app1@http:\/\/localhost:3001\/remoteEntry.js',\n                app2: 'app2@http:\/\/localhost:3002\/remoteEntry.js',\n            },\n            shared: {\n                react: {\n                    singleton: true,\n                    eager: true,\n                    requiredVersion: '^17.0.0'\n                },\n                'react-dom': {\n                    singleton: true,\n                    eager: true,\n                    requiredVersion: '^17.0.0'\n                },\n            },\n        }),\n        new HtmlWebpackPlugin({\n            template: '.\/public\/index.html'\n        }),\n    ],\n    module: {\n        rules: [\n            {\n                test: \/.jsx?$\/,\n                use: 'babel-loader',\n                exclude: \/node_modules\/,\n            },\n        ],\n    },\n};\n<\/code><\/pre>\n<h2>Step 4: Running the Micro Frontends<\/h2>\n<p>Navigate to each directory (app1, app2, and container) and run:<\/p>\n<pre><code>npx webpack serve\n<\/code><\/pre>\n<p>This will start the server for each application on their respective ports (3001 for app1, 3002 for app2, and 3000 for container). Open the container app in your browser at <a href=\"http:\/\/localhost:3000\">http:\/\/localhost:3000<\/a> to see your micro frontends in action!<\/p>\n<h2>Handling Routing Across Micro Frontends<\/h2>\n<p>One of the challenges of using micro frontends is managing routing. The container can handle paths and serve appropriate micro frontends based on the URL. You can extend the registerApplication function in the container to include more complex logic for handling different routes.<\/p>\n<h3>Example of Advanced Routing Logic<\/h3>\n<pre><code>registerApplication(\n    'app1',\n    () =&gt; import('app1\/App'),\n    location =&gt; location.pathname === '' || location.pathname === '\/app1'\n);\n\nregisterApplication(\n    'app2',\n    () =&gt; import('app2\/App'),\n    location =&gt; location.pathname === '\/app2'\n);\n<\/code><\/pre>\n<p>The example above checks the URL path and loads the relevant micro frontend accordingly.<\/p>\n<h2>Communication Between Micro Frontends<\/h2>\n<p>While micro frontends operate independently, there are scenarios where they need to communicate. One common approach is to use a central event bus, which can be implemented using JavaScript\u2019s built-in event mechanism.<\/p>\n<h3>Example Event Bus Implementation<\/h3>\n<pre><code>const bus = {\n    events: {},\n    subscribe(event, cb) {\n        this.events[event] = this.events[event] || [];\n        this.events[event].push(cb);\n    },\n    publish(event, data) {\n        if (this.events[event]) {\n            this.events[event].forEach(cb =&gt; cb(data));\n        }\n    }\n};\n\n\/\/ Example usage;\n\/\/ One micro frontend can listen for an event\nbus.subscribe('MY_EVENT', data =&gt; console.log(data));\n\n\/\/ Another micro frontend can publish the event\nbus.publish('MY_EVENT', { msg: 'Hello from app1!' });\n<\/code><\/pre>\n<h2>Optimizing Micro Frontends<\/h2>\n<p>As with any architecture, performance is key. Here are some best practices for optimizing micro frontends:<\/p>\n<ul>\n<li><strong>Code Splitting:<\/strong> Use dynamic imports in individual micro frontends to reduce initial load times.<\/li>\n<li><strong>Shared Libraries:<\/strong> Minimize the size of shared libraries to avoid bloating the application.<\/li>\n<li><strong>Lazy Loading:<\/strong> Implement lazy loading for routes that are not required immediately.<\/li>\n<li><strong>Network Requests:<\/strong> Ensure that API calls are called only when necessary.<\/li>\n<\/ul>\n<h2>Conclusion<\/h2>\n<p>Micro frontends architecture provides a flexible and scalable approach to developing complex web applications. By using React and tools like Single SPA and Webpack Module Federation, developers can easily implement micro frontends that enhance inter-team collaboration and improve code maintainability. We hope this guide helps you get started with creating your own micro frontends in React!<\/p>\n<p>Happy coding!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Creating Micro Frontends with React: A Comprehensive Guide In recent years, the concept of micro frontends has emerged as a powerful architectural style for building scalable, maintainable web applications. By enabling teams to work independently on different parts of an application, micro frontends facilitate parallel development and improve the overall agility of software delivery. This<\/p>\n","protected":false},"author":90,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[398],"tags":[224],"class_list":{"0":"post-7067","1":"post","2":"type-post","3":"status-publish","4":"format-standard","6":"category-react","7":"tag-react"},"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/namastedev.com\/blog\/wp-json\/wp\/v2\/posts\/7067","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/namastedev.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/namastedev.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/namastedev.com\/blog\/wp-json\/wp\/v2\/users\/90"}],"replies":[{"embeddable":true,"href":"https:\/\/namastedev.com\/blog\/wp-json\/wp\/v2\/comments?post=7067"}],"version-history":[{"count":1,"href":"https:\/\/namastedev.com\/blog\/wp-json\/wp\/v2\/posts\/7067\/revisions"}],"predecessor-version":[{"id":7068,"href":"https:\/\/namastedev.com\/blog\/wp-json\/wp\/v2\/posts\/7067\/revisions\/7068"}],"wp:attachment":[{"href":"https:\/\/namastedev.com\/blog\/wp-json\/wp\/v2\/media?parent=7067"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/namastedev.com\/blog\/wp-json\/wp\/v2\/categories?post=7067"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/namastedev.com\/blog\/wp-json\/wp\/v2\/tags?post=7067"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}