This content originally appeared on Level Up Coding - Medium and was authored by Rohit S
As web applications grow in complexity, teams seek scalable, modular approaches to frontend development. One such approach, Micro Frontend Architecture, allows breaking down monolithic frontends into smaller, independently developed and deployed units, similar to how microservices revolutionized backend systems. In this blog, we’ll explore the evolution of frontend development, the principles behind micro frontends, their benefits, and how key concepts like Module Federation and routing are managed in micro frontends.
Evolution of Frontend Development
In the early days of web development, frontend applications were relatively simple. Typically, developers would build static websites using HTML, CSS, and a bit of JavaScript. However, as the demand for dynamic and rich web experiences grew, so did the complexity of web applications.
The rise of frameworks like Angular, React, and Vue.js brought a significant leap forward by providing tools to build more interactive and data-driven applications. But these frontend applications were often developed as monolithic architectures — large, tightly-coupled codebases that grew difficult to maintain as teams expanded and feature complexity increased.
To address these challenges, developers turned to microservices on the backend, breaking monoliths into smaller, independently deployable services. As backend architectures became more scalable, it became clear that the same principles could be applied to the frontend - Micro Frontend Architecture.
What Is Micro Frontend Architecture?
A Micro Frontend is the frontend counterpart of microservices. Just as microservices break down backend monoliths into loosely coupled services, micro frontends break down a large web application into smaller, independent pieces that work together seamlessly to form a complete app.
With micro frontends, each part of the user interface (UI) can be developed and maintained separately. Teams can work autonomously, ensuring faster releases, better scalability, and enhanced performance.
Why to use Micro Frontend Architecture
- Independent Development and Deployment: Each micro frontend is an independent module, enabling teams to develop, test, and deploy features without affecting others.
- Technology Agnostic: Different micro frontends can be built using different frameworks (e.g., React for one part, Vue.js for another).
- Isolated Teams: Each team manages a specific feature or section of the app, with well-defined boundaries and responsibilities.
- Seamless User Experience: Although micro frontends are developed separately, the user experiences them as a single, cohesive application.
Example: Netflix
A real-world example of micro frontend architecture is Netflix. Their website is divided into different sections — like the home page, search, and user profile settings — each powered by a separate micro frontend. This approach helps Netflix reduce load times, as each section can be cached independently and updated as needed without affecting the entire website. It also enables rapid development and release cycles, as changes to one micro frontend do not disrupt others.
Micro Frontend vs. Microservices
While microservices focus on breaking down backend functionality into independent services, micro frontends apply this concept to the user interface.
- Microservices handle backend functionality (database operation, APIs).
- Micro Frontends manage the UI, handling the user interaction and presentation layer.
Despite this distinction, both share common goals:
- Loose Coupling: Each microservice/micro frontend functions independently.
- Autonomy: Teams can develop and deploy without needing to coordinate with other teams.
- Scalability: Each service or frontend can scale independently to meet user demand.
Micro Frontend — Integration Techniques:
- Asset Store: Store shared assets (like CSS, JavaScript) in a central repository, ensuring micro frontends can reuse and share common assets across the application.
- Module Federation: This webpack 5 feature enables micro frontends to share and dynamically load modules at runtime, allowing independent micro frontends to interact with each other.
- iFrames and Web Components: While this is not a true micro frontend techniques, these approaches provide encapsulation and isolation, especially for legacy systems.
Deep Dive into Module Federation
Module Federation is a powerful feature in webpack 5 that allows micro frontends to dynamically share JavaScript modules with one another at runtime. This concept addresses key challenges in micro frontend architecture — such as sharing dependencies, reducing duplication, and improving interoperability.
How It Works:
- Each micro frontend can expose its modules and consume modules from other micro frontends.
- Modules are loaded asynchronously at runtime, improving the initial load time of the application.
- Shared dependencies (like React) are loaded once and reused across different micro frontends.
Advantages:
- Dynamic Module Loading: Micro frontends can dynamically load modules as needed, reducing initial load times and enhancing performance.
- Decentralized Architecture: Teams manage their own modules independently, with no need to coordinate with other teams.
- Shared Dependencies: Dependencies can be shared between micro frontends, minimizing duplication and ensuring consistency across the app.
Simple Implementation Using React and Webpack
Let’s demonstrate how micro frontends work in React using Webpack’s Module Federation. We’ll build two simple apps:
- Host App: The main application.
- Remote App: A micro frontend that the host app will load dynamically.
Step 1: Setting up the Remote App
- Create a HelloWorld component (src/components/HelloWorld.js)
const HelloWorld = () => <h1>Hello from the Micro Frontend!</h1>;
export default HelloWorld;
2. Update webpack.config.js:
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { ModuleFederationPlugin } = require('webpack').container;
module.exports = {
mode: 'development',
devServer: { port: 3001 },
plugins: [
new ModuleFederationPlugin({
name: 'remoteApp',
filename: 'remoteEntry.js',
exposes: { './HelloWorld': './src/components/HelloWorld' },
shared: { react: { singleton: true }, 'react-dom': { singleton: true } },
}),
new HtmlWebpackPlugin({ template: './public/index.html' }),
],
};
3. Run the Remote App
npm start
Step 2: Setting up the Host App
- Install dependencies and configure Webpack:
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { ModuleFederationPlugin } = require('webpack').container;
module.exports = {
mode: 'development',
devServer: { port: 3000 },
plugins: [
new ModuleFederationPlugin({
name: 'hostApp',
remotes: { remoteApp: 'remoteApp@http://localhost:3001/remoteEntry.js' },
shared: { react: { singleton: true }, 'react-dom': { singleton: true } },
}),
new HtmlWebpackPlugin({ template: './public/index.html' }),
],
};
2. Load the remote component in src/App.js:
const HelloWorld = React.lazy(() => import('remoteApp/HelloWorld'));
function App() {
return (
<div>
<h1>Host App</h1>
<React.Suspense fallback="Loading...">
<HelloWorld />
</React.Suspense>
</div>
);
}
export default App;
3. Run the host app:
npm start
How It Fits In
This example showcases how Module Federation allows you to break down frontend monoliths by enabling apps (like the host) to dynamically load and integrate micro frontend modules (like the HelloWorld component) at runtime. This decouples teams, allows independent deployment, and lets you build scalable, modular frontend architectures while maintaining flexibility and reusability.
This lightweight, modular approach echoes how microservices revolutionized backend development. The same principles are applied on the frontend to improve performance, development speed, and scalability across large applications.
Handling Routing in Micro Frontend Architecture
Routing is a critical aspect of any web application, and managing it in micro frontends requires special attention to ensure a seamless experience. There are two common approaches to handling routing:
- Single Routing Layer (Shell): A central “shell” application manages all routing. It is aware of the routes of each micro frontend and delegates navigation to the appropriate frontend when necessary.
- Independent Routing: Each micro frontend manages its own routing internally, allowing for greater autonomy. The shell application might still manage the top-level routes but delegate deeper routes to the respective micro frontend.
Sharing Context and State in Micro Frontends
One of the challenges in micro frontend architecture is sharing state and context across multiple micro frontends. Here are some strategies to manage this:
- Global State Management: Use a state management tool (e.g., Redux, Zustand) that operates across micro frontends, allowing them to share a global context.
- Events and Pub/Sub Systems: Micro frontends can communicate with each other through event-based systems or publish/subscribe patterns, allowing for a decoupled interaction model.
- Shared Services: Use a shared service layer (e.g., API Gateway or GraphQL) to provide common functionality to all micro frontends.
When to Use Micro Frontend Architecture
Micro frontends are best suited for large, complex applications that require modularity and independent development. Here are key scenarios where they shine:
- Large and Complex Applications: Micro frontends help split large applications into manageable parts, improving organization and reducing build times.
- Multiple Teams: Teams can work independently on different parts of the app, allowing for parallel development and independent deployments.
- Independent Deployments: Micro frontends allow specific features to be updated without redeploying the entire app, reducing deployment risks.
- Different Technology Stacks: Different parts of the app can use different frameworks (e.g., React, Vue), allowing for flexibility in technology choices.
- Scalability: Micro frontends are easier to scale and maintain since each part of the app is isolated and can grow independently.
- Legacy Modernization: Replace legacy systems incrementally without a full rewrite, allowing a gradual transition to modern technologies.
- Performance Improvements: Optimize load times by caching or lazy-loading different parts of the app.
Avoid using micro frontends for small apps or projects with tight global state-sharing needs, as they add complexity that might not be worth the effort.
Conclusion
Micro Frontend Architecture is a natural evolution for modern web applications, allowing teams to build scalable, maintainable, and modular frontends. By splitting the frontend into independently deployable units, teams can work autonomously, manage dependencies more efficiently, and create a more flexible architecture.
With tools like Module Federation and carefully considered routing and state management strategies, micro frontends provide an exciting path forward for developers seeking to overcome the limitations of monolithic applications. Whether you’re working on a large-scale web app or just starting your frontend journey, micro frontends offer a way to build more scalable and maintainable systems.
If you enjoyed this blog, consider sharing it with others who might find it useful. Follow me for more such articles.
https://www.linkedin.com/in/itherohit/
Micro Frontend Architecture was originally published in Level Up Coding on Medium, where people are continuing the conversation by highlighting and responding to this story.
This content originally appeared on Level Up Coding - Medium and was authored by Rohit S
Rohit S | Sciencx (2024-09-16T02:21:54+00:00) Micro Frontend Architecture. Retrieved from https://www.scien.cx/2024/09/16/micro-frontend-architecture-2/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.