Monolith to Micro-Frontends


Many companies worldwide are considering adopting Micro-Frontends to improve business agility and scale, however, there are many unknowns when it comes to what the migration path looks like in practice. In this talk, I will discuss the steps required to successfully migrate a monolithic React Application into a more modular decoupled frontend architecture.



So, my name is Ruben Casas, I'm a staff engineer at Postman. The topic today is cool. We're going to talk about how to transform monoliths to micro front-ends. Okay? And now, this is our react conference, right? Yeah? Well, react has been here for a long time, right? Next year, react will be how old? Ten years old, right? So, recruiters will probably be like, oh, finally, we're going to be asking for ten years react experience. So react has been here for a long time. And it means that we have applications that are a bit old now. Technically, not old, old, but in the long scheme of things of technology, they're probably getting on a bit. And the problem with that is applications get old and they start growing and growing and growing. And what's the problem with growth? Well, the problem is stuff starts to break at some point. You know? And we'll probably be experiencing. Now, if you think, if you've been working with react, I guess, think what the problems you have right now, you probably will probably have a long session of people just complaining about the issues they have. But mostly, it's not about react itself. It's usually about the organization. It's about how as your company and the application grows, things start getting really more complicated and difficult to scale. So, you start getting things like, you know, exponential growth, like you have a lot of lines of code. You have more developers. You know, when you started that project, it was only two or three. Now, you have many groups of developers, especially for companies that are quite big. CI takes a long time to complete. We all hate that. We want things to be quick. Duplication of code. There is no clear ownership. Who owns what, et cetera, et cetera. So, we have a lot of problems. That dependency graph is the worst one. I hate it. Like, we have a lot of dependencies and we don't know where they're coming from or what is using what. So, there are a lot of problems. You're probably familiar with this. So, all of these problems have led a lot of people to think about micro frontends. Shall we use micro frontends to solve this problem? And people and a lot of companies are either implementing micro frontends or are trying to implement micro frontends. And there's only one issue with that is, you know, how do we do it? Where do we start? I have this big problem, this monolith, this massive application. How do we go from a monolith to micro frontends? Okay? But first... What are micro frontends? This is a joke. I'm not going to be explaining what are micro frontends. Every single talk about micro frontends starts with that slide. If you're not familiar, you can watch some talks about what they are. I'm going to be focused a bit more on how to go there rather than what they are. And I can touch on a couple of concepts. But that's the main goal of this... Well, actually, I'm going to tell you what's the main goal of this presentation. Do you want to know what's the main goal of this presentation? I'm going to make you smart. I'm going to make you look good. When you go to the next meeting, right, if you want to impress everybody in that room, right, I will show you, I will give you the key. Are you ready for the key? Once you're in that meeting, you just have to say, I think we need to find an opportunity to decouple these pieces. Right. Immediately. That will make you sound like the smartest person in that room. So decoupling the pieces, and that's Ryan Florence, by the way. Great quote. That's not me. Coupling is a big problem. And actually, the biggest thing than coupling is accidental coupling. That's the worst of all. So the main goal of... Well, not this talk, but the main goal of going from the monolith to microfrontends is to remove coupling, and accidental coupling. That is the main goal. Right? How do we achieve that goal? Well, I will show you in a minute, but the thing I like to say... This is my quote, by the way, I think, so I came up with it. People want to go to microfrontends, but they don't understand why. And this is a really good enough reason. If you want to go to a distributed architecture, if you want to solve those problems that you have with scaling a large monolithic application, you need to decouple it first. Otherwise, you will end up in the worst place from where you started. And actually, I have a talk about the risks of adopting microfrontends when you don't really need them. So before we can apply microfrontends, we should start with decoupling the system. And what's coupling? Well, there are many different types of coupling. But if you start noticing that things start changing together, you know, like code that changes together stays together, but if that code stays together, you start getting a lot of intertwined dependencies and things start just being really difficult to deploy independently or to have some sense of what the system is like. So before we go to distributed system, before we go to microfrontends, I think if we make our goal to decouple our codebases, that would be a goal achieved. So just remember, coupling. So that's the main goal. The main goal of microfrontends is to decouple the monolith, to try to make sense of that dependency graph, which I don't like having that big problem, and try to decouple the monolith. Okay, so there are many ways of achieving that goal of decoupling the monolith. Again, microfrontends is one of them. But today I will just challenge you. Please do try all of the other options. Do not go and say, okay, microfrontends is the solution. There are many solutions and I came up with a graph, like a diagram, which I call the decoupled and distributed spectrum, which is a long place where you can go from one to the next to the next until you solve your problem. We are going to talk about this and I'm going to explain this graph just briefly. So we have the monolith, right? That is where we are right now. And some people have the monolith with backend and frontend still, but let's assume that we don't have that. Let's assume that backend is already split into microservices. So we still have the monolith and we have the frontend application in the monolith. And we're struggling because we cannot deploy, it's very difficult, all these problems that we discussed briefly. Now, if I jump straight to microfrontends and I haven't explored all the steps in the middle, I'm just coming to this conclusion, which might not be the solution for my problem. So just remember, one of the main problems is decoupling. So how do we decouple? Let's take it step by step. Now let's try a modular monolith. This approach is also really good. Some companies are using it and they have their application a little bit more organized within their monolith. It's still a monolith, it's still deployed as one single unit, but they have some team ownership, they have some boundaries, they can make some sense of the application a bit better, and they still have some coupling. So we're still on the coupled scale rather than decoupled scale. But they cannot deploy independently. So that is one of the major things with modular monoliths, you still have to deploy the entire thing and you still have a lot of coupling inside. So all the UI and libraries and everything is in there. But for your company, for your use case, a modular monolith might be perfectly fine and might work and might solve a lot of your problems. So do check it out if you want to take a look at a modular monolith. And then the next step is, oh, what about integrated applications? Integrated applications are a bit more flexible than a modular monolith. There are many flavors and a lot of monorepo tools try to help you with an integrated application. Which is basically, you have multiple applications still inside one code base. It could be a monorepo. And they are deployed and composed at build time. So you cannot deploy independently still. You can still deploy, but once you release the application, this is the key, it gets released as one single unit still. So that's the main difference. Now finally we have arrived to microfrontend. So what do you get if you apply microfrontend? If you don't stop at the integrated applications and monorepos. And the key is independent deployments. So you will have independent deployments and runtime composition with microfrontends. Which means you don't have to deploy that single unit again at once. You can deploy those independent units separately. And that might be what you need. Or it might not be what you need. So it might be that independent deployments are going to cause a lot of problems. And actually there is a great talk just right after my talk by my good friend Alex. He's going to talk about exactly that, which is what if we don't go to independent deployments? What if we just keep an integrated application that is just composed of runtime? So don't miss it. It's after this talk. But I promised I was going to show you how to go from monolith to microfrontend. So we have decided, right, we need microfrontends, we need independent deployments. How do we do it? Right? So we need an action plan. And this action plan needs two things. We need a technical and an organizational plan. And I'm going to hopefully go through the technical and at the end we talk about the organizational. So the first thing is if you're deploying independently and you are composing things, you need to find how you're going to do, you know, how you're going to put everything together. And this is a very common way of splitting microfrontends, which is, you know, vertically by the root, the router and the URL, or horizontally, like widgets and stuff. But there are many ways of doing this. You can do this at the edge, you can do it server side, you can do client side. You need to choose a composition model. So let's imagine we have a react application. Just to keep it simple, it's a single page application, it's no service I rendered, and I'm going to choose a composition model based on client side rendering. And I'm going to be using a webpack module iteration, which is a great tool and I'll tell you why I like it. But basically we're going to keep it simple. Server side rendering composition is possible, it's just a bit harder. But if you have a single page application, react application, and you want to choose a composition model, this is a good one to go for with webpack module iteration. I told you why I was going to say why I like module iteration. One major thing, and it's very flexible. One important thing in this journey of monolith micro front-end is you need to make decisions reversible, that you do the transition gradually. Module iteration allows you to have that flexibility because I'm importing an external module using module iteration, and now I'm importing, oh, it's the same slide. Actually, it's not the same slide, I'm importing a local module. If I decide that module iteration is not my thing and it's not working for me, it's really easy to switch back to build time composition and loading from MPM rather than from module iteration. So making decisions that are reversible is very, very important. Because you don't want to go into a journey of, again, going to micro front-ends and you realise halfway through that, oh, this is not for us, that you have invested a lot into a technology and architecture that is going to be probably not very good for you. So that's why I like module iteration. Apart from that, do check it out, it's really good. It just allows you to compose your react components around time instead of build time. And it has a lot of features with dependency duplication, shared dependencies. So the next step is, right, we need to choose a router. Oh, I've switched back to say router because root and root sound the same, but we're in London, so a router is the next decision that we have to make. Because the router is the orchestration, it's what are you going to show on the screen. So this is a very important decision when you are moving from monolith to micro front-ends. Because how are you going to show one app or the other? So I have three options for you. The first one is a top-level router, which is basically just a normal router. Just think about just react router on your single-page application, that's exactly the same. There is no difference. It will be doing all the composition for you. It still acts as a one application. It's basically just react router. Not many difference. The only difference is those applications are loaded run time rather than build time. The benefits, well, simple. It's the same what you've been doing so far. So you probably be familiar with it. It's just a normal router. But we have a lot of coupling there. And this is where you need to fine-tune how much coupling you're going to tolerate in your new architecture. So the context is shared. It's one react application. You have to deploy the shell to deploy new routes because you have to basically someone has to tell what the routes are, the new ones. So you have to deploy two things. Still, that's coupling. So this one is good. For my use case, I like this one. I don't have a problem with sharing context and deploying my shell application. This works for me. If this doesn't work for you, then there is another option which is what I call the distributed multi-router or router. I'm going to be switching back and forth. So this one, the difference is there's no one router. There are multiple ones. So the top one, react router, yes, fine. And then all of these ones could be react router 5, 4, or whatever you want to use there. They are every single application will have their own router. And this is great. Each application is its own unit. They can basically deploy their own routes as they wish. They don't have to depend on anybody else to define and deploy new routes. And they're actually individual react apps. They do react on render separately. So they're not sharing anything or the tree or anything at all. They're absolutely completely independent apps. The problem I have with this model is it's very complex. I don't know if anybody has done it in production. I know there are a lot of material out there. It's very complex. You need to communicate between the routers. Only one router is allowed to use the browser history. The rest will have to do memory history and there will be a synchronization method. It's very complex. But you get absolutely 100% decoupled system. So if you're looking for absolutely 100%, there is not coupling at all, not even the react instances that are shared, then this is probably a model that you might consider. But there is also a couple of caveats. If I want some features from Reactor 6, which are great, by the way, they won't work because there is no shared context. And the final one, the one I have chosen for this architecture is, okay, what about a mix of both? For my main application, I have a router that is just a normal react router, single sharing context and I control it. But there is an application outside of this context that needs to be completely separate. There is another team. The company acquired a new startup and they're coming on board. They can use a separate router. So you can mix them. You still have some benefits, the same as the first one. You know, it's future proof. If a router goes away, you just change it. Backward compatible. You can use Reactor 3, 4, and Reactor 6. Or if you're into multiple frameworks, which you probably know I'm not a fan of, you can use vue. But there are no vue fans here. But this is complex. Communication is still hard and there is certain coupling on some of the parts here. I need to go quick. So what's the strategy? How are we going to achieve this? Now, the only thing that is guaranteed in a Big Bang rewrite is a Big Bang. So we can't do a Big Bang migration. And if you're trying to do a Big Bang migration, consider your choices. I don't recommend it. So how are we going to avoid the Big Bang migration? We are going to use a really common pattern. It's called the strangler pattern. I've talked about this before. It's basically your monolith will start loading little bits of the new application, which are in blue here, until you replace them all. And this works. I like the strangler pattern. It's great. You can even do widgets. You know, like, strangler pattern allows you also to just have in this URL that finance calculator is fine. It's just a new application. But today I will show you just a different approach. Strangler pattern is great. Do you know why it's great? We can tweak it much better. Well, maybe not much better. But an option is the reverse strangler pattern, where I'm going to put all of the code that is in the monolith, all the stuff that is in there, into my new shiny application. And I'm going to start doing something what I call shrinking the monolith, which is basically start taking those pieces of legacy code and then removing them, converting them into a brand new application. So this is what we're going to do. This is my option for this monolith to microfrontend recommendation. Reversing strangler pattern and start shrinking the monolith. Cool. So I told you that there were two parts. You know, the technical part, which I briefly discussed, and then the organizational plan. Microfrontends are trying to solve an organizational issue. Scaling, people, teams, et cetera. So it's not just technical. You can't just go to your decision makers and say, okay, we're going to use all this react, Composition, Modular Federation, when, in fact, most of the problems are in the organization. So things that you need to think about are a vision and strategy. So why do we want to do this? Please make sure that you ask this question every single time if you're thinking about microfrontends. Why are we using this? What are we trying to achieve? And that is the vision. Your vision will be why do we need microfrontends and why do we want to use microfrontends? Why is that going to give us? So that's the vision. And the strategy is, okay, how are we going to do this? How are we going to achieve that vision of introducing microfrontends to the organization? So that is the first one. The second one is establish a sense of urgency. You know, let's do microfrontends next quarter. Let's do microfrontends next year. There is a problem, and I've seen this a lot. There is a big issue. Oh, everything is on fire. Oh, I think microfrontends will be good. Then the fire is out and everything goes back to normal. And then, you know, the idea about microfrontends is probably amongst a lot of really good ideas. So if you're bringing this to your organization, just make sure that you say, okay, if we're going to do it, we need to make sure that we do it. Bring people on board. How do you convince your boss? That's a, or your technical leaders, that's a challenging one. But try to bring people on board. You know, try to say, okay, we are trying to achieve the same vision. And we can disagree on how we're going to get there. That's fine. But we can just try to, you know, be friends and bring them on board. And finally, be open to new approaches. Things change all the time. And this is why it's very important to have reversible decisions. If things change all the time, and you need to be open to changing your decision and making sure that it works for your organization. Because microfrontends are very specific to your organization. So it might not work for you. And with that, it's just the end. So that's the conclusion of our run out of time. But if you have any questions, again, my name is Ruben Casas. If you have any questions as well, just follow me on Twitter and just give me a ping. And I'll be more than happy to answer them. Thank you. Thank you. Thank you. Thank you.
22 min
21 Oct, 2022

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