Micro-Frontends Performance and Centralised Data Caching

Bookmark

Common myths about Micro-Frontends hold that they are bad for performance or that developers implementing this architectural style don’t care about the performance implications because they are focusing on fixing the developer experience and organizational issues rather than focusing on the user experience, however, the reality is altogether different. Micro-Frontends are not inheritably bad for performance and, as is often the case in software development, making best use of the technology depends on correct implementation. This talk will demonstrate how Micro-Frontends can make your applications faster and more resilient while keeping the benefits of independent deployments.



Transcription


Hello, everybody, and welcome to my presentation. So today is a very interesting topic, and it's about performance. So my name is Ruben. I am a senior engineer at American Express, and this is my Twitter handle if you want to give me a follow. So what do I do at American Express? Well, I am part of a team that maintains a micro frontend framework called OneApp. It's like a meta framework that we use at American Express. And this framework is open source, and it's used by about 2,000 developers, so there is a 2,000-developer team at Amex that uses this framework. And it's also our applications are used by multiple customers worldwide. Now, the question is, when you have so many users, what's the first thing that comes to your mind? Oh, performance. We need to make sure that all those millions of users have great performance. Now, before we start with the performance section, I'm going to get this out of the way because we get this quite a lot. I've seen this tweet so many times. Are micro frontends a thing yet? The other one is, why can't we just use components? Let me answer that question briefly before we get into the performance section. Well, micro frontends, yes, they are a thing. And also, they've been around for a while, so it's not like they are a new thing or something that is, you know, brand-new technology. It's been around for a little while. And basically, what they can do is they can help you scale your applications by applying the same principles that you have for microservices to the frontend. Now, quick disclaimer here. I am not going to try and convince you that micro frontends are great and that you should come and start using them tomorrow. This is not why I'm here today. But if you use micro frontends, you will get really nice benefits, like the main one, in my opinion, is independent deployments. So if you have a large team, or multiple teams, they can deploy independently. They can just have their own repositories, and they can just have their own thing, CICD, everything sets up and they can deploy independently. Different parts of the website, of the web application, and the thing with one app is we don't have to restart the server. You can deploy a new version and it automatically uploads itself without restarting the server. It's all servers that are rendered. If I didn't convince you with this, I brought some pizza, if you want some pizza, but I'm not trying to convince you here. So now, there is a problem with micro frontends. A big, big problem. This problem is there are many misconceptions, and there are many myths around micro frontends. The biggest by far is they are bad for performance. Yes, that is the biggest myth about micro frontends. And let me just, there is one reason for this, and I found why people think that micro frontends are bad for performance. The reason is, well, people think that micro frontends are all about mixing libraries on the same page. So we have react, and angular, and vue, and svelte, and Infinity Dash on the same page. Is that what micro frontends are about? Well, let me just tell you this is a false myth, and that's why people think that micro frontends are bad for performance. The first thing they find about micro frontends is it's about react, and angular, and everything on a page. Let me just ask, is that a good idea? Is that a good idea? My friend Ken thinks it's a good idea. I'm joking, he doesn't. It's not a good idea. You can, yes, so you can use react and angular and all these frameworks on the same page, but just because you can doesn't mean you should. So although, and this is, there's only one case, one specific use case where it might be a good idea, it's not great, but where it's a valid use case of having multiple frameworks on the same page. This is the strangler pattern. Now, the strangler pattern is the best thing you can do if you are migrating from an old application like a legacy application to a new one. How many of you here had to rewrite your old AngularJS application into react? Me! It's very common. This is a very common use case. For the last five, six, seven years, we've been, you know, AngularJS is not good, let's replace it with react. What do we do? We just completely stop development, say to the product managers, I'm sorry, we can't do any more features because AngularJS is bad, and we can't maintain it, we need to replace it with react. The first thing they will tell you is, what? No, you can't do that. I mean, probably some people do it. But what the strangler pattern will help you do is it will help you incrementally transform your application. So you don't have to do like a big bang transformation release rewrite of the whole application. What you can do is start applying the micro front-end pattern and the strangler pattern to uplift different pieces of the UI. The best thing is, well, can we just start route by route? Yes, you can, but when you have multiple pieces on the same page that you need to change, and sometimes one page is a lot of work, it's like the entire application is one page, with micro front-ends, you can start from a very small part on that page that is going to use react, the rest is going to use angular, and then at some point, this is the key, you remove angular. You don't keep both on the same page. Because performance! Yes, we shouldn't do that. So this is the strangler pattern, and this is the only case where it might be useful to have multiple frameworks on the same page. So micro front-ends can be good for performance. Disclaimer there, like a star, fine print. It depends on your implementation. Like everything in architecture, it depends on how you implement it. So if you have an incorrect implementation of micro front-ends, they're going to be really bad for you. If you have a good implementation, they're going to be good for performance. So what I'm going to do next is I'm going to show you first how they can be good, also what to avoid, and how to solve the problems that performance issues that you might encounter if you use micro front-ends. Great. So the first thing is this is a nice freebie. This is for free. Kind of. Micro front-ends can help you reduce your bundle sizes. And, yes, we worry about bundle sizes still. We shouldn't ship so much javascript to our pages or to our users if they don't need it. So the first one is, because micro front-ends are independent units, they're their own thing there, then they will have their own javascript bundles, and you get code splitting out of the box. So you don't have to worry about code splitting and where to code split because every single micro front-end will have their own bundle. And those bundle sizes, we try, for example, we try to keep them small. We try very, very hard to keep them small for performance reasons. Okay, so this is a free one. One thing to avoid, and that's next, and it's duplicated dependencies. So, yes, having multiple dependencies. How many have had this problem where you are like all my applications have different dependencies that need to be shared, and we have done things like externals, webpack, and make sure that we can access the same code and have our bundle sizes again small. We should avoid duplicated dependencies because they're all using the same thing. Why do they have their own copies? This is especially bad, going back to the bundle size for people who have slow internet connections, mobile devices, so we all know this. We should avoid duplicated dependencies. Also, react, we can't have react duplicated on the same page. We can't have two copies of react on the same page. I don't know why. Actually, I do. I think I will explain it's something to do with the scheduler that they erase each other, all really, really clever stuff. We shouldn't have react, multiple copies of react on the same page. If the micro front-ends are independent, how do we do this? There are many ways you can do that. But this is awesome. There is a new thing called modiferation, and it has a really fun api called the shared api. When I saw this, I was like, wow, I've been waiting for this for so long, because I want to have my micro front-end to get their own copy of the dependency if they are rendering in isolation. If you're rendering in isolation, you need your own copy because you don't have any containers, you don't have any application providing that dependency, so you need your own copy of react. Let's say we have a second module, and that second module, or micro front-end, they also need react, and react on, and also my shared library, or whatever. So what happens is, if I'm rendering in isolation, fine, give me my copy of react. If there is another micro front-end and they're rendering on the same context, what the shared api is going to do is hold on a minute, I've already loaded this copy of react, let me just provide it to you for any other micro front-end or modules that request the same dependency. So, module federation especially is really good, even just for this api. If you don't want to adopt the whole thing, and we don't want to overcomplicate things with micro front-ends, this is a really cool feature of module federation, if you want to take a look, is the shared api. It's like externals but beyond. There is also something about scopes where you can have a scope A and scope B, and that dependency will have a scope so you don't have clashes. Take a look at the documentation for module federation. It's brilliant. Now, the second part of my talk is, okay, distributed data fetching. Let me just stop here. I know what you're thinking. You're looking at this like, what is this? What? No. So, we used to do, well, now, we are used to do this, which is basically I load my data on my page, I'm using next.js or any other meta framework you have, get your server-side props or whatever, and then that does all the server-side rendering, and then I pass the data to my components. You could also call data on your components, but this is more or less the pattern. Now, with microphone tents, what is this? This is different. Every single microphone tent is loading their own data. Remember, these ones, you can deploy them independently, so they're like mini applications. Before you shoot me and say, why is this? This is not right. Let me just explain why. Why? Why each microphone tent is loading their own data is because they need to be independent. So they need all the data to render, and they need to avoid that passing data down from other microphone tents because that will cause tiling coupling, and rule number one of microphone tents, if you don't want to have a hard time, do not couple your microphone tents. I have a blog post talking about the best practices, and that's the biggest one. If you start coupling your microphone tents, you stop having all the benefits, and you end up with the hated distributed monolith which is a mess. Nobody knows what it does, and, if you change something, it breaks everywhere else. That's completely the opposite of what microphone tents are about. So if we keep them independent, which means they load their own data, so we can reuse them everywhere, and that's one of the benefits of microphone tents is that they're portable and reusable. You can take one, put it there, it loads all the data they need, they don't need to worry about context or where the data is coming from, or if I need to put a container, and the container has to provide it, because they load their own data. What's wrong with this? If every single microphone tent is loading their own data, what is going to happen? Anybody? We are making so many api requests. So the user microphone tent is rendering in the header, they get the user data, the microphone tent dashboard loads the user, they load the data again, so we have three network requests. Is this bad for performance? Of course it is. This is like no. Why are you doing this? So we came up with a solution at Amex which was, okay, let's do a distributed share cache. How is this different from a normal cache? Like I explained with Modus Federation, if you're rendering your microphone tent in isolation, they get their own thing, their own cache, but we have a place where if any of the microphone tents have also requested the same data, we're like, hold on, I'm not going to make that api request, I'm going to give you the cache. Pretty standard caching stuff. So we created this very, very basic fetching library. It's not basic, it's simple. It's basically a wrapper around fetch. And it's called react hooks. And that's it. Well, actually, it's not. It has the caching layer. It was the simplest solution that we could find because we could have over-engineered and tried to find these many different solutions. This is not the only solution, by the way. This is what we did. So you probably, I can feel that some of the questions will be, can you use that? Yes, you can. But at Amex, we felt we need something very simple. So shall we just wrap fetch around the hooks and put a shared cache on top? Yes, it fixed our problem with multiple api calls on the same page. Now, this is the part that I always say, people, before we go to a conclusion, I have a demo, but, yes, it wasn't working like 20 minutes ago. So if it breaks, I always tell people, you should record your demos. Live coding is not good. And here I am doing live coding. Okay. So, can you all see? Yes, that's perfect. So we have a nice, very basic microphone tent set up here. We have our user microphone tent. Usually renders on the header. You have a header microphone tent. By the way, the most common use case for microphone tents, the most common that I heard is header and footer. You don't need it for anything else. That's probably your case. There are more advanced cases for large-scale companies, but if you have your company, it's got a team that is doing the header, and the header is so complicated, and the footer is so complicated, they have so many different things, and you want to make sure that all your other teams have the same version of the header and the footer, microphone tents will be a good idea if you want to implement it. And keep it simple. It doesn't have to be complicated. This is another myth about microphone tents. They don't have to be complicated. You can even start with iframes. I'm not saying go and use iframes, but it can be just iframes. So we have this very basic set up here with a header with some user, and I have some films, and you can see that the user microphone tent is rendering inside the films again, because why not? I want the user again there. I cannot pass the data down from here to there because I'm entirely coupling my user microphone tent with my film's microphone tent, and we all know now that that's bad. We shouldn't do that. So let's see what happens. So if I make this request, and it doesn't work. Oh, dear. Hold on. Let's restart the server. This is what I was worrying about. Yes, I think it's the Wi-Fi. There we go. So let me just do that again. Clear the network. What is that? That's no good. We have one, two, three, four, five different api requests. Yes, I don't want that because all my microphone tents are just loading the same data and they're just making different requests on the client. Now let's go to our VS code. The first thing we have is we have a provider. I don't want to go into details because this is just a demo. I'm not going to say this is how you use Fetch and all this is api and everything, and you can have a look, it's open source. But it's basically a react context, but the difference with this react context is it works across multiple environments, so it's like you have different microphone tents that have their own context and we just make sure that there is one only true context that keeps all the cache in sync. So what happens when I do that? Let's clear the Fetch network. That's much better. We only have two api requests. So we are going to get the user, we're going to get the films, and I already have the user data, so just give me the cache. Sounds good. Now, this is basic stuff. The main strength of our microphone tent framework is server-side rendering. One thing that is really hard on microphone tents is server-side rendering. That is really, really hard. Getting server-side rendering with microphone tents working is absolutely hard, and there are so many, you know, the creator of module federation is trying to make it work with next module federation. It's really hard. I think he managed to do it. So let's enable server-side rendering. So again, I'm not going to explain this. This is just like our version of get server-side props or get your data from the server. I'm making the same api call on the server and on the client. And see what happens. Oh, nothing happened. Hold on. We aren't expecting anything to happen because there is no fetch on the client. It's server-side rendering. If you don't believe me, let's do the proper test. This is how you hack html. There is. Server-side rendering. It's Luke Skywalker. It's working. And the trick is our micro front-end framework is keeping the cache between the server and the client in sync. So when the server is downloading the data, then the client is like, hold on, that data is already on the server, I already have my cache, why do I need to do a fetch request? Let's just get the cache data. The best thing about this is you can just switch between front-end and back-end data fetching. It's a really, really cool thing. That was my demo. It's very small. And just a conclusion. I don't know what I'm doing with time. I think we're good. But my conclusion is, well, when someone asks me why is all the micro front-end stuff is so complicated and I don't want to do that, there is also a very particular problem. So if you don't have that problem, why are you trying to fix it? It's fine. If you do have this problem, well, micro front-end can help you improve developer experience. There is a counter-argument. Are you saying this is just about developer experience? Yes, sort of, and organisational issues and scaling issues, but, at the same time, if you fix your developer experience, if you fix your organisational issues so your teams can deploy independently, they will be more efficient, which means if you have to fix a bug in production, you don't have to worry that the whole application is going to break because you need to make sure that all the test paths, if you just apply that patch to your micro front-end, and it's isolated, and it's decoupled, it means you can just deploy that, fix the bug, nobody else knew that was a bug. All the teams are carrying on doing their own thing. So it helps organisational issues as well as developer experience. But as we saw, they don't have to be bad for user experience. They can also be really good for user experience if we make them work for us and make all these performance issues go away. And ta-da! This is me. Thank you very much. Yes! Awesome! Thank you so much. Would you like to grab a seat and let's go through some questions. I'm going to pick the top three rated questions in the slider. That means that there are many questions. Yes, there were so many, and we won't be able to get through to all of them, so here's what. If you're here, make sure you grab them afterwards, and, if not, go over to the spatial chat and you'll be able to chat later in one of those rooms. I'm going to go with the top rated question. It's from Adam Turner. If you update something like a component library, maybe after rebranding, how can you ensure all teams update the shared dependency at the same time? Okay. So you can fix that problem. Basically what you should do is just have a team that can deploy that shared library. You can have multiple versions with Microfront Ends. There is a really... This is something that people are like, what? Microfront Ends have some versioning. You have 1.2.2, and if my orchestration says I want 1.2.3 and I'm not ready to update yet, then it's fine. They were like kind of dependencies but they are not dependencies because you can deploy them at run time. You don't have to come and download the MPM install, Microfront End 1.2.3, make sure you pass it. You don't have to do that. You just basically say 1.2.3 is ready for production, it's been tested, I now want to load it into my page. Done. So that is... We can go... That's a great answer. The next question is from Levi. How do you maintain coding style and conventions over multiple Microfront Ends and the teams that are working on them? Kind of an organizational. This is an organizational one and it's a good one because, again, Microfront Ends is like an answer to organizational issues. They are the technical answer, but the organizational answer, it depends on your company. We recommend or I recommend your company to have what we call the devops team, or the div, like as a div, to just make sure that they take care of their component libraries, make sure that everybody is following the same style, and you can just create templates. Every single Microfront End, you have a generator or template, someone is making the decisions, and just make sure that you follow the same coding practices that you do with anything else. Only difference is that these ones are... You don't have to talk to them. They can do their own thing and they can deploy independently. They don't have to talk to anybody to deploy a new version. And last but not least, this one is from Jafen. You mentioned performance issues with multiple frameworks on the same page. Would you say this still applies with compiled frameworks like svelte? I am not an svelte expert. I've tried it. I'm not sure. I mean, the main reason that there is a problem with having multiple frameworks on the same page is obviously you're loading a lot more javascript. So if you load angular and vue, so with svelte, if they're not loading any javascript, we need to look at, you know, I'm not sure how they're going to clash. It's not like you can't do it. I mean, you can. And you could do some optimisations to get around it, and as I mentioned, there is a use case for it. So, when you have angular as your old application, well, you need to optimise for that. There's no way around it because you're upgrading. So, yeah, you could optimise it and svelte doesn't have any client-side stuff that is going to make your application huge, then potentially, yes. Thank you so much. I really enjoyed that talk. I'm a big fan of LiveCode and so happy that you did it as well. Give him a round of applause. But one more thing before you leave the stage. You have to pick your favourite question so that person can come to the front or maybe find us online and get a T-shirt. Which was your favourite question? Okay. I think the versioning one is interesting because people don't ask that one very often. Which one? The versioning. The versioning one. If that was your question at the next break, come find us over at the front. If you're online, we will contact you. And thank you so much. Thank you once again.
27 min
22 Oct, 2021

Check out more articles and videos

We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career

Workshops on related topic