Skip to main content

Micro-Frontend Fundamentals

Table of Contents


Introduction

The Microservice architecture has become increasingly popular in software development, proving its superiority across various systems. However, while backend services can adopt Microservice architecture, what about the user interface?

This article explores the application of Microservice principles to frontend development. Historically, frontend development in large systems has followed a monolithic approach, even as the backend has embraced microservices.

Though frontend source code is often modularized into reusable components, it still functions as a monolithic web app. This raises the question: Does the frontend need a microservice architecture similar to the backend?

In this articles, I'm using slaves or sub-application to mention the application which expose assets (like micro-services), and master app or host app to mention the gateway app, which handle navigation, slaves assets loading and life-cycles.


Real-World Challenges

Issues

When developing a frontend application:

  • Team members contribute to the same codebase, often in their own styles.
  • As the project scales, it becomes harder to manage:
    • Increasing folders and inconsistent coding styles.
    • Long build times due to many dependencies.
    • Deployment delays caused by interdependent teams.
    • Performance issues in production, such as loading numerous JS/CSS files.
  • Integrate existing codebase to another.
  • Slaves die in production
  • Communication between sub-apps
  • CSS, JS isolation problems

Current Solutions

  • Folder management: Each team organizes their code within a single directory.

  • Coding styles: Establish uniform conventions across teams.

  • Build resource issues: Invest in additional hardware resources. When using bundle tools like Webpack Federation or Vite, we could use NX workspaces or TurboRepo instead to handle caching and build-related problems. They're most efficient when running directly on server, without any docker or k8s infrastructure.

  • Heavy production apps: Implement lazy loading, SSR, or Server Components.

  • Redirect to sub-app or rewrite all: using domain/subdomain to navigate between apps, or rewrite all codebase.

  • Slaves die: we need errors boundary layer in master to handle this case, or the master may be down when just one slave is down. Further more, we need caching layers, through CDN or cache should be implements to handle such cases.

  • Communicate between apps: There're multiple method to communicate between apps, like localStorage, lifting state up to master app, or using share store (cross-store calling). The easiest way when integrating apps is communicate through the master app, because they usually share small piece of state like user info, global app state,... When building micro-frontend app from scratch, better using some state-management which allow cross-store calling thus it easier to manage. Beware of the access role of the slaves, as they may override state of others. We should list out RBAC of slaves and handle it when writing state into store.

  • CSS, JS Isolation: There no CSS or JS isolation. We should handle loading these assets properly. Keep in mind that the assets only need to load only once. So common assets should be share by some library-apps to load it just one time, avoid conflict. With the CSS, we should named it with care, usually with prefix of each slave, or, you will have to reload the whole application to reset app state :))

Evaluation

Unlike the backend, frontend development demands a unified codebase for development, building, and deployment. This leads to challenges in scaling monolithic frontend systems.

The solution? Micro Frontend Architecture.


Understanding Micro Frontends

Definition

Micro Frontends extend the principles of Microservices to the frontend. They enable breaking down an app into smaller, independent units such as components or screens. Each unit can be developed, deployed, and maintained independently.

Structure

Figure 1: Micro-frontend Structure

Advantages

  • Supports multiple frameworks and versions.
  • Simplifies application management.
  • Enables independent CI/CD processes.
  • Reduces deployment size and speeds up builds.
  • Facilitates easier upgrades and testing.
  • Encourages collaboration across teams.

Disadvantages

  • Complex configuration and setup.
  • Challenges with global state management.
  • Security issues requiring backend expertise.
  • Dependency management complexity.
  • Risk of code duplication and inconsistency.

Comparing Micro Frontend Architectures

Monolithic Frontend

A single repo contains all frontend and backend code, leading to tightly coupled systems.

Structure

Figure 2: Monolith Structure

Micro Frontends

Frontend components are split by functionality and deployed independently. This mirrors the modular nature of microservices in the backend. Additionally, each module or slave app can be develop independently.

Structure

Figure 3: Micro structure


Loading Methods for Micro Frontends

  • Iframe: Easy to implement but limited in navigation and JavaScript execution. If you familiar with Google Maps Iframe or Payment Gateway, it can be embed into your page like a component. There is some method to overcome these limit of iframe, we'll dive into it in ViettelDMP case, but in my perspective, it should be avoid. Check this article

Structure

Figure 4: Loading apps using iframe.

  • Proxy (e.g., Nginx): Maintains connections between host and micro-apps but reloads entire pages during navigation. With framework like single SPA, we leverage this to navigate between slaves app without reload. Proxy like Nginx play role in redirect requests into slaves.

  • Web Components: Framework-agnostic custom elements that integrate seamlessly but require advanced expertise. We don't have much experience on this approach so I currently leave this section empty. But there are some reference you can check here and Github. Also you can Check this web component example

  • Bundle Tools: Use tools like Webpack Module Federation or Vite for efficient micro-frontend integration.

  • Framework: Qiankun and SingleSPA, simplify building step, specially integrate existing application. They provide application level life-cycle to handle render slaves.


Essential Components of a Micro Frontend System

  1. App Manager (Host): Resolves dependencies and initializes micro-apps.
  2. Loader: Fetches and loads unresolved micro-apps from the server.
  3. Router: Routes URLs to appropriate micro-apps.
  4. Micro AppStore: Manages shared states across the system.

Structure

Figure 5: Micro-frontend structure.


Micro Frontend in JHipster

JHipster provides a robust generator for creating Micro Frontend architectures, leveraging Webpack Module Federation. We explore this more in SMEStore case study.

Advantages

  • Fast implementation with pre-configured tools.
  • Optimal standards for projects.

Disadvantages

  • Requires deep knowledge of JHipster.
  • Limited documentation.
  • Restricted to ReactJS, AngularJS, and VueJS.
  • Micro Frontend features are experimental.

Real-world examples

  1. Iframe (Run-time) Challenges:

    • Poor performance (e.g., embedding Google Maps).
    • Security concerns with embedding apps in external pages.
    • Bug-prone development.
  2. Web Components (Run-time)

    • Custom elements integrated as HTML tags across frameworks.
  3. Module Federation (Build-time)

    • Efficiently shares modules between apps during build, supported by tools like Webpack. Check this example
  4. Qiankun and SingleSPA

    • SingleSPA

      • SingleSPA is a versatile micro frontend framework designed to help developers orchestrate and manage multiple frontend applications. It provides lifecycle methods and APIs to integrate micro-apps seamlessly.

      • Key Features

        • Framework Agnostic: Supports React, Angular, Vue, or even vanilla JavaScript applications.
        • Lifecycle Management: Handles mounting, unmounting, and updating micro-applications.
        • Flexible Routing: Allows custom routing strategies for seamless transitions between micro-apps.
        • Customization: Offers high flexibility, though it requires more manual configuration.
      • Use Cases

        • Integrating apps built with different frontend frameworks.
        • Decoupling large monolithic frontend applications.
      • Advantages

        • Strong community support.
        • Framework independence.
        • Works well with Webpack Module Federation for dynamic dependency sharing.
      • Challenges

        • Steeper learning curve compared to Qiankun.
        • Requires more manual setup for advanced features.
    • Qiankun

      • Overview

        • Qiankun, built on top of SingleSPA, simplifies the development of micro frontends with additional abstractions and powerful features. It is popular in the Chinese tech ecosystem but widely applicable globally.
      • Key Features

        • Out-of-the-Box Setup: Provides ready-made solutions for common micro frontend challenges.
        • Enhanced Isolation: Ensures that micro-apps operate in their own sandboxed environments.
        • Built-in Dependency Management: Simplifies resource loading and dependency sharing.
        • Dynamic Loading: Supports dynamic loading of micro-apps.
      • Use Cases

        • Building micro frontends with minimal manual setup.
        • Organizations favoring a plug-and-play approach.
      • Advantages

        • Easier to use for beginners.
        • Offers sandboxing and resource isolation by default.
        • Great for rapidly integrating multiple micro-applications.
      • Challenges

        • Slightly opinionated due to its abstractions.
        • Limited flexibility compared to SingleSPA for highly customized use cases.

      Comparison

      FeatureSingleSPAQiankun
      Framework SupportReact, Angular, Vue, etc.React, Angular, Vue, etc.
      Ease of UseModerate to High (requires setup)High (out-of-the-box features)
      SandboxingNot checked yetBuilt-in
      Dependency SharingVia Module Federation or manualBuilt-in
      CustomizabilityHighModerate
      Learning CurveSteeperEasier