A first idea would be cookies, yet you can run out of space really fast.
3 Answers
There are several ways to get communication in microfrontends.
As already noted the different microfrontends should be loosely coupled, so you'd never directly talk from one to another.
The key question is: Is your microfrontend solution composed on the server-side or client-side?
For the client side I've written an article on the communication.
If you are on the server side (question seems to go in that direction due to the mention of cookies) then I would suggest using the standard microservice patterns for communication and exchanging state. Of course, using centralized systems such as Redis cache there would help.
In general the different microfrontends should have their own state and be as independent as possible.
Usually what you want to share is not the state / data, but rather the state with an UI representation. The reason is simple: That way you don't have to deal with the representation and edge cases (what if the data is not available?). One framework to show this is Piral.
Hope that helps!

- 3,041
- 19
- 25
-
2great article @Florian https://dev.to/florianrappl/communication-between-micro-frontends-41fe – Juanma Menendez Sep 06 '21 at 16:46
There's no shared state, that'd break the concept of the segregation that's supposed to take place. This pattern is present among all microservices architectures as it's supposed to eliminate single points of failure and other complications in maintaining a bigger store. The common approach is for each "micro frontend" to have its own store (i.e. Redux). The Redux docs have a topic on this.

- 1,933
- 2
- 15
- 32
First, you should avoid having shared states between MicroFrontend (MFE) much as possible. This is a best practice to avoid coupling, reduce bugs, etc..
A lot of times you don't need it, for example, every information/state that came from the server (eg: the "user" information) could be requested individually for each MFE when they need it.
However, in case you really need a shared state there are a few solutions like:
- Implement the pub/sub pattern in the Window object.
There are a few libraries that already provide this.
//MFE 1
import { Observable } from 'windowed-observable';
const observable = new Observable('messages');
observable.publish(input.value); //input.value markup is not present in this example for simplicity
//MFE 2
import { Observable } from 'windowed-observable';
const observable = new Observable('messages');
const handleNewMessage = (newMessage) => {
setMessages((currentMessages) => currentMessages.concat(newMessage)); //custom logic to handle the message
};
observable.subscribe(handleNewMessage);
reference: https://dev.to/luistak/cross-micro-frontends-communication-30m3#windowed-observable
- Dispatch/Capture Custom browser Events Remember that Custom Events can have 'details' that allow pass information
//MF1
const customEvent = new CustomEvent('message', { detail: input.value });
window.dispatchEvent(customEvent)
//MF2
const handleNewMessage = (event) => {
setMessages((currentMessages) => currentMessages.concat(event.detail));
};
window.addEventListener('message', handleNewMessage);
This approach has the important issue that just works for 'new events dispatched', so you can read the state if you don't capture the event at the moment.
reference: https://dev.to/luistak/cross-micro-frontends-communication-30m3#custom-events
In both implementations, using a good naming convention will help a lot to keep order.

- 17,253
- 7
- 59
- 56