Micro Frontends (MFEs) Without the Mess
Micro Frontends: Solving Library Conflicts & Styling Inconsistencies

Micro Frontends (MFEs) Without the Mess

In today’s evolving web landscape, Micro frontends (MFEs) have emerged as a powerful architectural pattern. They allow teams to work independently on different parts of an application, improving flexibility and speed. However, this approach comes with challenges, and one of the biggest is library conflicts and inconsistent styling.

Each MFE (micro frontend) may use different JavaScript frameworks, UI libraries, or CSS libraries, which can lead to integration headaches. In this blog, we'll explore these challenges and a structured approach to solving them. But first, let’s briefly introduce micro frontends to those who don't know much about it.


What Are Micro Frontends (MFEs)?

Micro frontends apply the microservices concept to the frontend. Instead of having one large monolithic frontend, the UI is made up of multiple, smaller applications (MFEs) that work together.

Key Features of Micro Frontends:

  • Each MFE is designed to be developed independently and, in many cases, can also be deployed independently. You can also choose a centralized deployment approach based on project needs.
  • A Host, Master Page or Container Page integrates all MFEs into a single user interface.
  • Different teams can work on different MFE using their preferred tech stack.

A Visual Overview of Micro Frontends Architecture

While this approach provides flexibility, it can introduce inconsistencies in code, UI components, and dependencies. Allowing each team to pick its own framework, UI and CSS library may sound good in theory, but in the long run, it can create serious problems.


The Case for Standardization

Framework Standardization

In my view, it is better if all teams use one approved framework or library for all MFEs. Over time, If a framework or library like Knockout.js, Backbone.js, or jQuery etc. becomes outdated, teams can switch to a new framework for future development. This way, coding standards remain consistent, and it makes it easier to move developers between MFE teams, reducing the learning curve.

Let's say we have finalized React as the framework for development.

The Next Challenge: Standardizing Libraries

Even when all teams use the same framework, there is still a chance that teams might choose different libraries (like Bootstrap or Tailwind, Material UI, or Joy UI, Axios or Fetch). We can fix this by also approving a single library for each task across all MFEs. For example, let's say we've finalized Material UI as the component library.

Component Library Challenges

Even after selecting Material UI as the component library, several problems can still arise:

  • Version Inconsistencies: One team might use Material UI 6 while another sticks to an older version like Material UI 5, causing UI inconsistencies. ??
  • Conflicts and Redundancy: Multiple versions of the same library can increase the app size and cause unexpected behavior.
  • CSS Overlaps: Without a common style, one team’s CSS might override another’s, leading to layout problems.
  • Higher Maintenance Costs: As the codebase grows, updating library versions in all MFE's becomes increasingly difficult, especially if a library becomes obsolete.

This challenge isn't limited to only component libraries. For example, consider network libraries like Axios or Fetch. If they become obsolete or develop vulnerabilities, replacing them individually across every MFE would be a significant challenge.

The Best Solution: A Shared Library

A shared library is the most effective way to maintain consistency across MFEs. Instead of adding a library (like Material UI) directly into each MFE, we build a separate, shared library that contains all the UI components.

This ensures that:

  • Every micro frontend adopts the same UI components, styling conventions, network call methods, and internationalization practices.
  • Versioning is controlled centrally.
  • Updating or replacing a library in future for any reason becomes easier.

Let's take example of Material UI again. Instead of adding Material UI directly to every MFE, we can build a separate component library that includes Material UI and creates our own versions of the controls. Each MFE then uses this common library. You can share it as an npm package or use module federation based on your project’s needs.

Example: A Standard Button Component

Here is a simple version of a Material UI button in our component library:

// Button.js
import React from 'react';
import MuiButton from '@material-ui/core/Button';

const variantMapping = {
  primary: 'contained',   // Primary action style
  secondary: 'outlined',    // Secondary action style
};

export const Button = ({
  variant = 'primary', // Accepts 'primary' or 'secondary'
  onClick,
  children,
  ...props
}) => {
  const mappedVariant = variantMapping[variant];
  return (
    <MuiButton variant={mappedVariant} onClick={onClick} {...props}>
      {children}
    </MuiButton>
  );
};        

Now, every micro frontend must use this shared button instead of directly importing Material UI’s button. If we ever need to switch to another UI library (for example, Joy UI), we only update the component library rather than every MFE. Consider this alternative implementation using Joy UI:

// Button.js
import React from 'react';
import JoyButton from '@mui/joy/Button';

const variantMapping = {
  primary: 'solid',         // Primary action style in Joy UI
  secondary: 'soft',        // Secondary action style in Joy UI
  ghost: 'plain',           // Minimal style option
};

export const Button = ({
  variant = 'primary', // Accepts 'primary', 'secondary', or 'ghost'
  onClick,
  children,
  ...props
}) => {
  const mappedVariant = variantMapping[variant];
  return (
    <JoyButton variant={mappedVariant} onClick={onClick} {...props}>
      {children}
    </JoyButton>
  );
};        

Documentation Challenges

When creating shared libraries on top of existing ones like Axios, Fetch, or Globalize, developers might not need extensive documentation. However, for component libraries documentation is essential. For example, Material UI has great documentation and demos. However, if you build your own component library, creating and keeping documentation up to date for all teams can be a big task. If teams don’t know how to use the components, they might still create their own versions, leading to inconsistencies. Fortunately, there are tools to help with this.

Some Tools for Documentation & UI Testing

You can consider following tools/libraries to document UI and Components

  • Storybook – Most popular tool, Best for large-scale projects, provides visual documentation and UI testing.
  • Ladle – A lightweight alternative, great for small-to-medium projects.
  • Histoire – For Vue-based micro frontends.
  • React Styleguidist – Helps document React components efficiently.

Using these tools ensures that all teams have access to the guidelines and documentations and makes component adoption seamless.


Bringing It All Together

By combining MFE architecture with shared libraries, teams can work independently while maintaining consistency across all MFEs and avoiding integration challenges. The key is to standardize not only the UI components but also all other dependencies, such as network libraries and internationalization libraries.

Key Takeaways:

? Adopt one framework and a set of common libraries for all MFEs to ensure consistent coding and styling standards.

? Build centralized libraries for recurring functionalities, whether UI components, network utilities, or other dependencies, to simplify version management and updates across all MFEs.

? Use tools like Storybook, Ladle, or Histoire to provide clear, accessible documentation and guidelines that help all teams stay aligned.

This structured approach helps teams achieve flexibility without sacrificing consistency, making micro frontend development more scalable and maintainable.

At the end, I would like to extend my sincere thanks to Jeffrey Ulman for his guidance during my last assignment. His mentorship played an important role in shaping the ideas presented in this blog.

Usman Rahim

ERP Specialist / Product Manager / Technical Business Analyst / Technical Project Manager / ERP Techno Functional Consultant

3 周

Feeling great delight in my heart to know it coming from you, Waqas Idrees.

Nazim Hussain

Sr Software Engineer at Stewart Title

3 周

Very informative

要查看或添加评论,请登录

社区洞察

其他会员也浏览了