Unlock Cross-Micro-Frontend State Sharing!
Published: 2024-03-18 07:53:23


# Sharing State Across Micro Frontends with MicroLocalStore

In modern web development, the micro-frontend architecture has gained popularity due to its modularity, scalability, and ability to develop large applications as a composition of smaller, independent applications. However, one of the challenges with this approach is sharing state across these micro-frontends in an efficient and secure way.

Enter MicroLocalStore, a lightweight JavaScript library that provides a shared local storage solution across different origins. In this article, we'll explore how to use MicroLocalStore to share state between micro-frontends, enabling seamless communication and state management.


![MicroLocalStore Demo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tlofun5dp80r841fgwq1.gif)

## What is MicroLocalStore?

MicroLocalStore is a JavaScript library that creates an isolated local storage for each instance, allowing you to store and retrieve data seamlessly across different origins. It's designed specifically for micro-frontend architectures, enabling different micro-apps to share state without conflicts.

With MicroLocalStore, you can easily manage state listeners, send and receive messages between parent and child windows, and more. It's compatible with both browser and Node.js environments.

## Installation

You can install MicroLocalStore using npm:

```bash
npm install micro-local-store
```

Alternatively, you can use the unpkg CDN in your HTML file:

```html
<script src="https://unpkg.com/micro-local-store"></script>
```

## Usage

Let's dive into a simple example to understand how MicroLocalStore works.

### Setting Up MicroLocalStore

First, we need to create a new instance of MicroLocalStore and provide a unique identifier and an array of allowed URLs that can share the store's state.

```javascript
const store = new MicroLocalStore("myStore", [
  "https://example.com",
  "https://another-example.com",
]);
```

### Setting and Getting State

You can set the state using the `setState` method, which will merge the new state with the existing state.

```javascript
store.setState({ key: "value" });
```

To retrieve the current state, use the `getState` method.

```javascript
const state = store.getState();
```

### Listening for State Changes

MicroLocalStore allows you to listen for state changes by registering a listener function with the `onChange` method.

```javascript
store.onChange((newState) => {
  console.log(newState);
});
```

You can remove a listener function by calling the `offChange` method.

```javascript
store.offChange(listener);
```

## Example: Sharing State Between Micro Frontends

Let's consider a scenario where we have two micro-frontends, `App1.html` and `App2.html`, hosted on the different domains (`https://example.com`, `https://another-example.com`). We want to share state between these two micro-frontends using MicroLocalStore.

### App1.html

```html
<!DOCTYPE html>
<html>
  <body>
    <button id="trigger">Trigger State Change</button>
    <div id="state"></div>

    <script src="https://unpkg.com/micro-local-store"></script>
    <script>
      const store = new MicroLocalStore("myStore", [
        "https://example.com/App1.html",
        "https://another-example.com/App2.html"
      ]);

      // Get state
      const state = store.getState();
      document.getElementById("state").innerHTML = JSON.stringify(state);

      // Listen for state changes
      store.onChange((newState) => {
        document.getElementById("state").innerHTML = JSON.stringify(newState);
      });

      // Set state on button click
      document.getElementById("trigger").addEventListener("click", () => {
        store.setState({ key: "value from App1" });
      });
    </script>
  </body>
</html>
```

### App2.html

```html
<!DOCTYPE html>
<html>
  <body>
    <button id="trigger">Trigger State Change</button>
    <div id="state"></div>

    <script src="https://unpkg.com/micro-local-store"></script>
    <script>
      const store = new MicroLocalStore("myStore", [
        "https://example.com/App1.html",
        "https://another-example.com/App2.html"
      ]);

      // Get state
      const state = store.getState();
      document.getElementById("state").innerHTML = JSON.stringify(state);

      // Listen for state changes
      store.onChange((newState) => {
        document.getElementById("state").innerHTML = JSON.stringify(newState);
      });

      // Set state on button click
      document.getElementById("trigger").addEventListener("click", () => {
        store.setState({ key: "value from App2" });
      });
    </script>
  </body>
</html>
```

In this example, both `App1.html` and `App2.html` create a new instance of MicroLocalStore with the same identifier (`"myStore"`). They also specify the URLs of the other micro-frontend that is allowed to share the state.

Each micro-frontend listens for state changes using the `onChange` method and updates its UI accordingly. When the "Trigger State Change" button is clicked, it sets a new state using the `setState` method, which will be reflected in both micro-frontends.

## Cross-Origin Resource Sharing (CORS)

MicroLocalStore uses the `postMessage` API to communicate between different windows. This requires that the server hosting your application allows the URLs of the other applications to access your application. This is controlled by the server's CORS policy.

When creating a new MicroLocalStore instance, you must provide an array of URLs that are allowed to share the store's state. These URLs must be allowed by the server's CORS policy.

If you're using Express.js, you can use the `cors` middleware to set up your CORS policy. Here's an example:

```javascript
const express = require("express");
const cors = require("cors");

const app = express();

const corsOptions = {
  origin: ["https://example.com", "https://another-example.com"],
};

app.use(cors(corsOptions));

// Your routes here

app.listen(3000, () => {
  console.log("Server is running on port 3000");
});
```

In this example, `https://example.com` and `https://another-example.com` are allowed to access your application.

## Conclusion

MicroLocalStore provides a simple and efficient way to share state across micro-frontends, enabling seamless communication and state management. By creating an isolated local storage for each instance and allowing cross-origin communication, MicroLocalStore makes it easy to build modular and scalable web applications using the micro-frontend architecture.

Give MicroLocalStore a try in your next micro-frontend project and experience the power of shared state management across independent applications.