
State Management in Micro Frontends
State management is how you handle data and the condition of a software application. It means organizing and refreshing the info an application needs to work, like what users enter, data from the backend, and settings.
Good state management helps an application run smoothly and gives users a good experience. Techniques and tools for this include local, global, and state containers.
For web applications, state management is about handling and refreshing the data and condition of the application. This is key to making dynamic and interactive web pages that react to what users do and provide a smooth experience.
With client-side state management, data is handled in the user’s browser using things like cookies, local storage, and session storage. This allows fast data access, but it's limited by the user’s device storage and possible security issues.
Server side state management handles data on the web server, allowing stronger data storage. This uses session management, caching, and server side databases.
Well known state management tools for web applications are Redux, React Context API, and MobX for client side, plus Node.js, Django, and Flask for server side.
Micro frontends are a web development method where a single application is made from different builds. It's like a microservices approach, but for client side single page applications in JavaScript.
It's an architectural approach where each frontend part is separated into its own application. This lets teams work on frontends on their own, using different tools. By splitting frontend work into smaller applications, teams can work better and deliver good frontend experiences.
By utilizing micro frontends, a multitude of advantages can be gained, including,
Independent development - Micro frontends allow teams to develop and deploy front-end functionality independently, without having to coordinate with other teams. This reduces dependencies and enables faster development and deployment.
Flexibility - Different teams can choose different frameworks and technologies for their micro-frontends. This allows teams to work with technologies that best suit their needs and expertise.
Reusability - Micro frontends can be reused across different projects or applications. This reduces development time and promotes consistency in frontend design and functionality.
Maintainability - With micro frontends, each application is focused on a specific feature or functionality. This makes it easier to maintain and update specific parts of the frontend without affecting the rest of the application.
When state management is used between micro frontends, it can introduce some challenges that can undermine the benefits of the micro frontend architecture. By coupling each frontend to another, it becomes harder to manage and develop each frontend independently, defeating the purpose of using micro frontends.
In the context of a web application, state management is used to manage the shared state across different components or pages. However, when this is extended to micro frontends, it can lead to dependencies between the micro frontends, making it harder to maintain and update them independently.
The diagram below illustrates the problem of coupling between micro-frontends that occurs when using state management:
As shown in the diagram, the shared state becomes a point of coupling between the micro frontends. Changes to the shared state can have a cascading effect on the different micro frontends that depend on it, making it harder to maintain and update them independently.
Hence, increasing the usage of state management techniques results in minimizing the interdependence between different micro frontend applications.
In certain scenarios, it becomes necessary to handle state management within the micro frontends. In such cases, the following strategies can be implemented to effectively manage the state between different micro-frontend applications.
Use local storage
Web applications can now easily use local storage, which means you don't need extra code to create a single place for keeping track of your app's data. Using this, each small part of your app can get the data in local storage and do what needs to be done.
Local storage lets coders simply handle data between the small parts of their apps. Keep in mind that local storage can only hold so much data. Make sure to think about this when you're planning and building your app.
Implementing a Shared API Utility
One way to improve the performance and reliability of a web application with micro frontends is the creation of a shared API utility micro frontend. This micro frontend caches all fetch/XHR requests and responses. This minimizes the request size, which enhances performance. It reduces network requests and improves application responsiveness.
The individual micro frontends can all call into the shared API micro frontend when making a request, which gives the API micro frontend the ability to decide whether or not to refetch data based on its freshness. This method aids in reducing the overheads of network requests, thereby enhancing efficiency and minimizing errors or inconsistencies across the micro frontends.
Developers can build a more reliable and scalable web application with the micro frontend architecture. By efficiently managing the flow of data between micro frontends and maintaining consistent state across application. The shared API micro frontend can cache requests and responses, which can help optimise the performance of the application and make it faster.
Create exported functions
Let’s consider this strategy using Single Spa framework. In Single SPA, you can share state between different frontend applications by exporting functions from one application and importing them in another. One way to do this is to create a shared module that exports functions that other applications can use to get or set the shared state.
For example, let’s say you have two applications - App1 and App2. App1 has some shared state that App2 needs to access.
You could create a shared module in App1 that exports functions for getting and setting the shared state,
Then, in App2, you can import these functions and use them to access the shared state:
Note that the shared state in this example is just a simple object, but it could be any data structure or even a state management library like Redux or MobX. Also, make sure that the shared module is loaded before the other applications that depend on it.
Using custom browser events
Custom browser events can be used for state management in micro frontends by dispatching events from one micro frontend to other micro frontends that are interested in the state change. To do this,
Define custom events - Define custom events that represent state changes in your micro frontends.
Dispatch events - When a state change occurs in a micro frontend, dispatch the corresponding custom event using window. dispatchEvent() method. Listen for events: In the other micro frontends that are interested in the state change, listen for the custom event using window. addEventListener() method.
Update state - When the custom event is received, update the state of the micro frontend accordingly. It’s important to note that using custom browser events for state management can be complex and error-prone, especially in larger and more complex applications.
Using libraries
There are several libraries that can be used for state management in micro frontends. Here are some of the most popular ones,
Zustand redux micro frontend (Microsoft) Let us explore the approach of employing the Zustand library to facilitate the distribution of state across micro frontends,
To manage the state in micro frontends using Zustand across two apps, you can use a shared state management solution to synchronize the state between the two apps. Here’s an example,
With this setup, both App 1 and App 2 have their own independent Zustand stores, but the state is synchronized between the two apps using the combine function from Zustand. The combined store provides a unified view of the state from both apps and can be used in other components to access and modify the shared state.
Using state management solutions in micro frontends is usually considered bad practice, as it may couple unrelated applications and ultimately deprive micro frontends of their benefits. In some situations, share state between micro frontends will be inevitable. The recommended solution is, however, to keep the state as simple as possible. To achieve this, there are multiple means of handling the state between micro frontends, depending on the requirements and constraints of the application.