Micro Frontends: Breaking the last Monolith
Are micro frontends the future of web development? Or are they just another tech buzzword with no value? Let’s talk about how micro frontend architecture can make development easier by allowing different parts of an application to be developed, tested, and deployed independently.
The Monolith
Software Monoliths are single logical executables. In other words, everything needed to mount a software project is contained within a single codebase.
Back in the day, all the business logic of websites was located in a single codebase. So we usually had both the Backend and the Frontend living together. I’m not saying this is a bad choice, because that architecture is still used today and we have some great examples of sites that used it wisely. But let’s face it, as the codebase grows, it becomes harder and harder to add new things and manage deployments. Not to mention that new hires can have a hard time finding their way through a giant pile of generalist code.
So this architecture looks like this:
Keeping the front end with the server meant that for every page request, the server needs to send the whole HTML body to the browser, thus making the experience of navigating through a site much slower.
For that reason, as the internet started to focus more on user interaction and user experience, frontends kind of became their own thing. That’s when a new paradigm emerged and tried to solve most of the problems present in the Big Monolith.
Single Page Applications and Micro Services
So with this architecture, we broke the Big Monolith into 2 smaller and more specialized monoliths. This time people are keeping the backend apart from the frontend, so each codebase specializes in one of the two. The frontend now interacts with the backend using API calls and live on its own. This architecture looks like this:
Breaking big problems into smaller ones is a great way of reducing code complexity, so the Backend monolith eventually was broken into smaller, specialized, and self-sufficient units, called microservices.
Now each domain of the business could have its microservice, with its own environment variables, deployments, and databases. Also, services can be scaled up and down independently as demand for each microservice increases.
But we still have one last monolith left: The Frontend!
Breaking the last monolith
So even with all the progress and innovations, frontends still suffered from most of the problems all monolithic codebases had.
The more the frontend monolith grows, it becomes harder and harder to add new features, because it will likely have a lot of code coupling and shared logic.
Another big disadvantage is that if a developer needs to make a simple frontend adjustment, the CI would have to build the entire package from scratch, so the build time can take hours to take effect.
Not to mention some weird bugs and CSS style overrides that we have no idea where they’re coming from.
With that in mind, what is the most simple way of resolving all of those problems? What if we tried to break the front-end monolith? Let’s talk about Micro Frontends.
By definition, a Micro frontend is an approach to developing web apps as a composition of small frontend apps. The application is broken down into domain-specific micro frontends, which are self-contained and can be developed and deployed independently.
Advantages of Micro Frontends
1- Autonomy
Just like microservices, micro frontends are autonomous and loosely coupled. That allows us to modify and deploy them independently and multiple teams can build them in parallel without sharing the codebase.
2- Single Responsibility
Each micro frontend is responsible for a single task or responsibility. This makes them easier to develop and maintain. It also makes them more responsive to change, since you can make changes to a single micro frontend without affecting the entire application.
3- Technology Agnostic
Micro frontends can be built using any technology stack. This makes them a great choice for companies that want to use a variety of technology stacks for their different applications. It doesn’t matter if it’s Vue, React, or Svelte, we can have all 3 of them in the same application working together.
4- Faster and Independent Deployments
The bigger the codebase, the more it takes to build and deploy. Some projects can take several hours to run all the tests and build all the packages. So if someone needs to make a simple change or ship a fix to an incident, that could take hours. With micro frontends, since the domains are separated into smaller units, we can build and deploy them independently.
Disadvantages of Micro Frontends
1- Software Standards
If each development team chooses a specific code standard for each application, micro frontends can become a chaotic mess. It’s very important for companies that exercise micro frontends to keep everyone on the same page with clear guidelines and documentation.
2- Additional DevOps effort
Another key disadvantage is the additional DevOps effort. Since each micro frontend is deployed separately, it’s harder to get it all working, especially if we have multiple environments.
3- With small projects and small teams, it’s just not worth the struggle
Adopting micro frontends is a good idea if your project is big and has more than one front-end team. With a small team, it is not worth the struggle. If the project is small and certainly won’t grow much, the good old monolith will be fine.
How to implement Micro Frontends?
Nowadays there are many ways of achieving similar results. Let’s talk about those.
Build-time Composition
The most common way of implementing this approach is by having a container app that npm installs the other micro frontends and ties them together at build time.
The main disadvantage of this approach is that if someone makes a change in one of the child micro frontends, the root module needs to be rebuilt again. This raises concerns that different teams won’t be able to independently build and release changes to their frontends. However, there are modern tools to solve this problem, like Bit.
I won’t get into more details about this tool, but if you’re interested in this approach, feel free to visit their webpage.
Serverside Composition
Then we have the server-side approach, which uses the server to mount the pages by retrieving the micro frontends from CDNs, then assembling them all as pages to user browsers.
The major downside here is that serverside is by far the most expensive, especially if we have very customized pages that can’t be cached.
Runtime Composition
It’s the process of assembling micro frontends into a larger application at runtime. This can be done in several ways, such as by using a frontend router or by dynamically loading components as needed.
1- IFrame
One very common way is by using the good old IFrame. Those are HTML elements that can be embedded into other HTML pages. They also offer a good degree of isolation of styles and are simple to maintain. The different Iframes talk to each other with an Event Bus, so components emit events that are heard by other components, so on and so forth.
However, with IFrames It’s difficult to build integrations between different parts of the app, so routing, history, and deep-linking become a headache.
2- Web Components
The Web Component approach is kind of similar to the IFrame approach, but here we are using web components to wrap micro front ends so they can be used together.
3- Module Federation
This is where it gets interesting for me. With this approach, we usually have a container app that we call host or shell, and that application loads the other micro frontends at runtime, as needed. Each micro frontend is completely independent and if we make any changes to it, as soon as the micro update is deployed, the entire app will be updated for everyone.
With the release of Webpack 5 and Module Federation, micro frontends that use runtime composition became easier than ever.
Conclusion
Breaking an application into smaller, more manageable pieces, micro frontends can make it easier to develop, test, and deploy. They can also improve performance and scalability. This pattern has been adopted by major companies like Microsoft, Spotify, and IKEA with good approval from developers who practice it.
There’s no doubt that micro frontends have huge potential. They pose as a solution to most of the problems that come with traditional monolithic applications, but let’s see how this technique unfolds and matures into more robust solutions.
In the next article, I’ll show you how to implement micro frontends using the new Module Federation from Webpack and deploy them using Github Actions and AWS (S3 + Cloudfront). So stay tuned! ;)