DEV Community

Cover image for ⚔️ Cross micro frontends communication 📦

⚔️ Cross micro frontends communication 📦

Luís Takahashi on October 10, 2020

In this article, I'm going to explain some ways to communicate between multiple applications and a particular way that I have chosen to use in my c...
Collapse
 
florianrappl profile image
Florian Rappl

Really nice article - well done!

There is, however, one problem with events: You only get notified in case of changes. Especially for your problem statement (sharing some global state) you'd be interested in the current snapshot when starting. So this assumes that all interested parties are already there when the state modifier starts submitting events. This, obviously, is in general not the case. Here, you'd end up with strange situations.

A more reliable solution would be to come up with events in both directions; i.e., one to get informed about the current snapshot (originating from interested microfrontends) and one to inform about changes to the snapshot (originating from the modifier).

One problem I see with the windowed-observable lib is that it hides what it changes on window. Sure, now every microfrontend can embed this and presumably it still works (if more or less compatible versions are used) but what if somebody tries to use __shared__ for other purposes.

Thanks again!

Collapse
 
vbarzana profile image
Victor A. Barzana

I was gonna say this but you arrived first, good point 😉 Well, you can always come up with an unique name and document it in your overall app architecture so that no one messes up with the shared thingy. Maybe this could even be configurable in your build process as an environment variable with the build number or what not. About having a snapshot of what has happened when your micro rendered is a must, so others can track/react to already triggered events.
This was really a nice article to read. Looking forward to more of your content.

Collapse
 
florianrappl profile image
Florian Rappl

Unfortunately it's not so easy. The name has to be known by the microfrontends which are build and deployed independently.

Thread Thread
 
luistak profile image
Luís Takahashi

Hum... to solve it those keys/namespaces could be wrapped in another package which exposes only the communication API, and every micro-frontend uses this API

Collapse
 
luistak profile image
Luís Takahashi

@vbarzana This kind of comment made my day, I'll try to create more content for sure!

Collapse
 
luistak profile image
Luís Takahashi

I'm glad you liked it ❤️

Yep that's the main problem using the window someone may interfere in those keys 😥

Collapse
 
dgreene1 profile image
Dan Greene

@florianrappl it's a fair point, but at a certain point don't you have to simply trust the developers and hope that you hired the right people? Also, I think documentation, training, and on-boarding at the company should help tell people that you only communicate between microfrontends through the use of the recommended library (i.e. don't touch/read directly from window, use the library instead).

Nice work @luistak

Collapse
 
ricardoaruiz profile image
Ricardo Ruiz

Fala Luiz.
Tudo bem?

Cara primeiro dizer que gostei muito do seu post. Muito bom mesmo...
Queria tirar umas dúvidas com você a respeito da funcionalidade de "Retrieving latest event". Estou com uma necessidade aqui no trabalho de utilizar a comunicação entre MF's e pelo que li na documentação e vi em seu video a sua lib se encaixaria muito bem, porém, acredito que não estou sabendo utilizar muito bem essa funcionalidade de obter o último evento.
Poderia trocar uma ideia?

Valeu

Collapse
 
chimchim2 profile image
Chim

This was one of the few articles worth reading in at least month. Thanks for the work you put into this. It's something I've banged my head for the past year and you just shined light on the darkest part of using this pattern. Thank you

Collapse
 
luistak profile image
Luís Takahashi

This kind of comment really cheered me and pushed me to write more! I'm really glad you liked it, I held this article for a long time thinking it wasn't good enough.

I hope it helped at least a little in this matter o /

Collapse
 
sunzehui profile image
sunzehui

really nice, thank you for your share!

Collapse
 
dgreene1 profile image
Dan Greene

I like the window observable approach you've recommended, but I think it's important to list that it has a "con" to the approach: It misses type safety.

Sure, you can change the type in the interface from T extends any to T extends unknown and that will help a little bit. But that doesn't solve the problem that occurs when a MicroFrontend falls out of date. To phrase that as a question:

What does the observing MicroFrontend (let's call her "O") do when the publisher (let's call her MicroFrontend "P") changes the structure of the event that it's publishing?

For instance:

// in P's code on Monday
obs.publish({ foo: "bar" })
// in O's code on Tuesday
const { foo } = obs.listen();

// in P's code on Friday
obs.publish({ body: { foo: "bar" } });
Enter fullscreen mode Exit fullscreen mode

What happens?

Well, MicroFrontend O is going to have a runtime error since there was no requirement to re-compile/re-deploy MicroFront O after MicroFrontend P changed it's code.

Note: Consider subscribing to me, as I'll be writing my own article on this specific problem, and I'll likely refer to yours as a starting block. Thank you for your hard work @luistak.


Enter fullscreen mode Exit fullscreen mode
Collapse
 
luistak profile image
Luís Takahashi

Over that problem, I would suggest creating a new abstraction that will always handle both sides and exposes a consistent API that may not change

This is the same problem as Rest api's

I've seen some folks solving this problem versioning their endpoints, so another solution would be versioning those namespaces to something like:

const observable = new Observable('v1/items');

const observable = new Observable('v2/items');
Enter fullscreen mode Exit fullscreen mode

And each version would have different responses

Collapse
 
josemunoz profile image
José Muñoz

I'm going to start a migration project next month and I'm gonna use micro-frontends to approach this project, one of the things I was considering for state management is the webworker solution here! One change I would make is that I'd have a redux store on the webworker and standardize redux over both apps, great article!

Collapse
 
luistak profile image
Luís Takahashi

Hi José o/

Good luck with your project!
I don't really recommend using redux as a global state in a worker, consider sharing only the essential information

If two micro frontends are frequently passing state between each other, consider merging them. The disadvantages of micro frontends are enhanced when your micro frontends are not isolated modules.

This quote from single-spa is awesome and also try to avoid "over-reduxing"

Collapse
 
rivernotflowing profile image
River

don't see the need for any of this which will add another platform dependent part into my application. Most react applications already use either mobx or redux, they are platform agnostic. I'm sure what ever library you use on Angular or Vue should expose observable or subscription api too.

Collapse
 
luistak profile image
Luís Takahashi

Hi River!

The main message I was willing to pass was those types of sharing information between multiple micro-frontends, for sure your app may not need to do it what is also great!

Collapse
 
chandramuralis profile image
Murali Srinivasan

Is there any better way to securely communicate a short data between two separate Angular Applications that don't run in the browser at the same time.
For example, send some JSON data from example.com/firstAngularapp to example.com/OtherAngularApp ?

Collapse
 
luistak profile image
Luís Takahashi

For sure if they're at the same domain you can use localStorage or any relevant web storage/db to sync that data

Collapse
 
icebob profile image
Icebob

Great article!

Collapse
 
luistak profile image
Luís Takahashi

Thank you! I hope you liked it

Collapse
 
yash_nigam profile image
Yash Nigam

I have a use case in which i have to communicate from iframe to parent and vice-versa
i know how to solve it but i am unable to change the existing code base of windowed-observable
We have to replace the window object with window.top and build it.

If there is any issue with this approach we can discuss

Collapse
 
stokry profile image
Stokry

Nice article, thanks for sharing.

Collapse
 
luistak profile image
Luís Takahashi

You are welcome o/ 😌

Collapse
 
nubunto profile image
Bruno Luis Panuto Silva

It's a pleasure to see you writing content! Great article and keep it up!