cozde-logo

Micro Front-End and Six infinity Stones

Micro
Minh PhanMar 30, 2023
Micro Front-End and Six infinity Stones

If you're a fan of the Marvel Cinematic Universe, you're probably familiar with the concept of the Infinity Stones. These powerful gems were scattered throughout the universe, and when brought together, they gave their wielder ultimate power. In a way, micro front-end development is like collecting the Infinity Stones - each micro front-end module is a piece of the puzzle, and when put together, they create a powerful and flexible application.

In this post, we'll how they work together to create a seamless user experience, discuss how to structure a micro front-end application, and provide practical advice on how to implement one.

1. Micro front-end props and beyond

we'll explore the six "Infinity Stones" of micro front-end development and how they work together to create a seamless user experience.

1.1. The Mind Stone: Micro Front-end Architecture

The first step to building a powerful micro front-end application is to establish a solid architecture. This is where the "Mind Stone" comes in - it represents the foundational knowledge needed to build a successful micro front-end architecture.

1.2. The Time Stone: Dynamic Loading

The "Time Stone" represents the ability to dynamically load micro front-end modules as needed. This is essential for building a scalable and performant application, as it allows modules to be loaded on demand, rather than all at once.

Dynamic loading is usually achieved through asynchronous module loading, where modules are loaded only when they are needed, rather than all at once. This can significantly improve the initial load time of the application, as well as reduce memory usage and improve overall performance.

1.3. The Space Stone: Module Isolation

The "Space Stone" represents the concept of module isolation - ensuring that each micro front-end module is independent and does not interfere with other modules. This is achieved through techniques such as sandboxing, encapsulation, and versioning.

Isolation is important because it allows modules to be developed and deployed independently without affecting other parts of the application. It also allows for easier testing and maintenance, as each module can be tested in isolation.

1.4. The Power Stone: Framework Agnosticism

The "Power Stone" represents the ability to use multiple frameworks within a micro front-end application. This is achieved through framework agnosticism - allowing each module to use the framework that best suits its needs.

Using multiple frameworks within an application allows developers to take advantage of the strengths of each framework and create a more powerful and flexible application. It also allows for easier integration with existing systems and technologies.

1.5. The Reality Stone: Cross-Platform Compatibility

The "Reality Stone" represents the ability to run micro front-end applications across different platforms and devices. This is achieved through cross-platform compatibility - ensuring that each module can be run on different platforms without modification.

Cross-platform compatibility is important because it allows micro front-end applications to be deployed on a wide range of devices, from desktop computers to mobile devices and beyond.

1.6. The Soul Stone: Data Sharing

The "Soul Stone" represents the ability to share data between micro front-end modules. This is achieved through techniques such as custom events, message passing, and shared state management.

Data sharing is important because it allows modules to work together and share information, creating a more seamless and integrated user experience. It also allows for more efficient use of resources, as modules can share data rather than duplicating it.

2. Micro front-end structure

To structure a micro front-end application, you'll need to create separate directories for each micro front-end, as well as a directory for shared resources, such as common styles, fonts, or images. Each micro front-end should have its own directory structure, including the components, services, views, and any other relevant files.

Here's an example directory structure that could be used for a micro front-end architecture:

micro-front_end-root ├── @routing-module ├── @module-a ├── @module-b ... ├── shared-components ├── shared-assets ├── shared-services └── README.md

Explaination folder structure:

  • shared-components: Make this module as common stylings for the whole business and every modules inside this project can re-use the components instead of defining over again inside each modules
  • shared-assets: images, icons, etc
  • shared-services: control the service controller for all modules to communicate to middleware/back-end

Note: In further, you can also separate your utils/hooks logic into a dedicated module

3. Practical implementation

Implementing a micro front-end architecture requires careful planning and coordination. Here are a few practical tips to help you get started:

3.1. Choose the right technology stack

When building a micro front-end architecture, it's important to choose a technology stack that supports modular development and deployment. Some popular options include React, Angular, and Vue.js, as they provide tools and libraries to help you build modular applications.

My own advices would be some trendy techs as below:
For each sperated modules:

  • ReactJS
  • Redux, Redux-toolkit (global cross-state control management)

For shared-components:

  • tailwindcss (class stylings, theme provider, etc)
  • Marteial-UI/Ant-design (optional)
  • storybook (document and preview shared components)

For shared-services:

  • axios (fetcher instance)

Tips: you can use the RTK-query or React-query for caching and indicator or manually implement them.

3.2. Use Git submodules

Git submodules can be used to manage the dependencies between the micro front-ends and the shared code repository. This allows each micro front-end to reference the shared code repository as a submodule, making it easy to update the shared code across all micro front-ends.

For example: Adding the submodule into your micro root repository

git submodule add <module-git-url> <module-name>

3.3. Share data between micro front-ends

Sharing data between micro front-ends can be challenging because each module is typically developed and deployed independently. However, there are a few ways to share data between micro front-ends, such as API calls, the Pub/Sub pattern, or shared state management libraries such as Redux or MobX.

3.4. Control routing your micro front-end

In a micro front-end architecture, routing can be controlled in different ways depending on the specific implementation. Here are three common approaches:

  1. Centralized Routing: This approach uses a central routing mechanism that sits outside of the individual micro front-end applications. The central router is responsible for receiving requests from the user and deciding which micro front-end application to load. This approach requires careful coordination between the different teams responsible for each micro front-end to ensure consistency and compatibility.
  2. Embedded Routing: With embedded routing, each micro front-end application has its own internal routing mechanism. When a user navigates within a micro front-end, the embedded router handles the routing within that micro front-end. If a user navigates to a different micro front-end, the embedded router hands off the request to the central router.
  3. Hybrid Routing: A hybrid approach combines elements of both centralized and embedded routing. The central router is responsible for handling high-level navigation between micro front-ends, while each individual micro front-end also has its own internal router for handling internal navigation.

Here's an example of how you could use a separate routing module in a micro front-end application built with React:

import { BrowserRouter as Router, useNavigate } from "react-router-dom"; import { useRoutes } from "react-router"; import React from 'react'; import ReactDOM from "react-dom"; import { loadMicroApp } from "./microAppLoader"; const root = ReactDOM.createRoot( document.getElementById("root") as HTMLElement, ); const Header = () => { const navigate = useNavigate(); const handleNavigate = (path: string) => navigate(path); return ( <div> <button onClick={() => handleNavigate("/home")}>home</button> <button onClick={() => handleNavigate("/microapp1")}>micro1</button> <button onClick={() => handleNavigate("/microapp2")}>micro2</button> </div> ); }; const Routes = () => { const routes = useRoutes([ { path: "/microapp1", element: loadMicroApp( "microapp1", "http://localhost:3001", ), }, { path: "/microapp2", element: loadMicroApp( "microapp2", "http://localhost:3002", ), }, ]); return ( <React.Suspense fallback={<div>loading...</div>}>{routes}</React.Suspense> ); }; root.render( <React.StrictMode> <Router> <Header /> <Routes /> </Router> </React.StrictMode>, );

The loadMicroApp function is responsible for loading the micro front-end from its URL and returning a React component that can be rendered by the main application. Here's an example implementation of the loadMicroApp function:

export const loadMicroApp = (name: string, microAppUrl: string) => { return <iframe title={name} src={microAppUrl} />; };

In this example, the loadMicroApp function returns a new React component that is responsible for loading the micro front-end script from the specified URL.

3.5. Monitor and troubleshoot your micro front-end architecture

When deploying a micro front-end architecture, it's important to monitor and troubleshoot your application to ensure that it is working as expected. This includes monitoring your micro front-ends for errors, as well as monitoring the performance and availability of your application as a whole.

4. Conclusion

In conclusion, a micro front-end architecture can help you break down a large, complex front-end application into smaller, more manageable parts. By structuring your application in this way, you can develop, test, and deploy each micro front-end independently, making it easier to maintain and scale your application over time. To implement a micro front-end architecture, you'll need to choose the right technology stack, use Git submodules, share data between micro front-ends, test each micro front-end independently, and monitor and troubleshoot your application.