DEV Community

Peeter Tomberg for Engineering as a Service

Posted on • Originally published at fvst.dev on

Unleashing the Power of Micro Frontends: Breaking Free from Monolithic Applications

Embark on a transformation journey as we explore the challenges of a monolithic Single Page Application (SPA) and the solution: micro frontends. Discover how code splitting, server-side rendering, and modularization improve performance, scalability, and agility. From independent development and deployment to seamless scalability, this article unravels the benefits and potential downsides of adopting micro frontends. Join us as we revolutionize front-end architecture and embrace the future of web development.

Humble beginnings

We started many years ago with a single-page application, bundling code up with webpack and serving it to the customer. Once the application loads, navigating between pages is super fast as we only fetched the necessary data to render the new page.

So what problems does this approach have?

  • All of the rendering is pushed to the client; if the client's phone is not the strongest, they will wait a while for our application to render on their phone.
  • All of the code is sent over the network to the customer for all of the pages in our system. Not problematic if you have 1 or 2 pages, but the more complex your system, the more the customer has to download. And downloading takes time.

With our application's complexity growing with each new feature we pushed, we also increased the amount of javascript the client has to download, parse, and execute.

The problems started to grow when we were acquiring new customers in a new market — previously, we had people on iPhones using a 4g connection, and they loaded our site within seconds, while the market users had older generation Android phones using 3g and sometimes it took 60 seconds just to load our site. Change was needed

Server Side Rendering and code splitting to the rescue? We thought so too…

We implemented code splitting, which significantly reduced the amount of Javascript we were shipping to the customer. We added server-side rendering so we could ship HTML to the customer, reducing the time the customer has to spend looking at an empty screen. Everything was faster and felt faster, so what’s the problem?

It turns out that what we called a Single Page Application was actually a monolith and shared the same problems.

  • The application is too large and complex to fully understand and make changes fast and correctly.
  • The size of the application can slow down the build/start-up/deployment time.
  • You must redeploy the entire application on each update.
  • The impact of a change is usually not very well understood, which leads to do extensive testing.
  • Continuous deployment is difficult.
  • Monolithic applications can also be difficult to scale when different modules have conflicting resource requirements.
  • Another problem with monolithic applications is reliability. Bug in any module (e.g., memory leak) can potentially bring down the entire process. Moreover, since all instances of the application are identical, that bug will impact the availability of the entire application.
  • Monolithic applications have a barrier to adopting new technologies. Since changes in frameworks or languages will affect an entire application, it is extremely expensive in both time and cost.

What if we split up our front end into multiple smaller frontends? How would that work?

First off, we need something to distribute requests between these systems. We picked Nginx to handle this task, so let us start by implementing Nginx in front of our existing monolithic SPA.

Secondly , we start gathering user functionality in a single system. Let’s take the ID system first — it’s a system that handles signups, logins, and account recovery. We implement that functionality in our micro front end with server-side rendering and code splitting. We deploy our micro frontend separately and configure Nginx to route traffic with the prefix /id to our id micro frontend

Thirdly we change our monolithic SPA routing so that all URLs starting with /id perform a full page navigation instead of our SPAs route event. Once we’re happy with the results, we can remove the id part of the code from our monolith.

What benefits did we get from doing this?

The ID part of your system is now a separate small system that you can:

  • develop independently without having to know the entire system. You could even have separate team work on this system.
  • build quickly as the scope of the system has decreased immensely
  • test easily as you have barriers between systems. Any changes you make to your id system can not break down the monolith and vice versa.
  • deploy separately — no need to wait for other parts of the system to be production ready; deploy your micro frontend when you’re ready!
  • scale based on traffic — some of your system pages will be accessed more than others; with micro frontends, you can configure part of your website to be scaled differently.
  • rewrite to another language or framework without having to rewrite the entire system.

Turns out that the benefits of micro frontends are the same as microservices!

This can’t be all good now, can it?

You’re right; this approach also has a few downsides.

  • You must maintain the look and feel across different systems — a design system helps with this challenge!
  • Making changes across your entire front end is difficult — you must make changes to each part of the front end in isolation. Look into mono-repositories; turborepo is a really cool one! Have all your systems in one place and enjoy making changes that span across systems.
  • Having to make libraries to share code between micro frontends — your micro frontends will have a lot of repetition, and abstracting it away to a library is a need. Mono-repositories like turborepo will help you with this problem as well!

Alternative solutions

This solution was built about three years ago — since then, we’ve seen Module Federation gain popularity. This essentially means your application dynamically loads and executes Javascript on demand (similar to code splitting); the difference is that it dynamically loads a completely different application while sharing some of the dependencies (e.g., React or Angular).

Module federation is built around client-side rendering. It can support server-side rendering, but it’s not in a state where I would recommend using it in production just yet.

Conclusion

In conclusion, adopting micro frontends offers a transformative solution to the challenges posed by monolithic Single Page Applications (SPAs). Businesses can achieve enhanced performance, scalability, and agility by leveraging code splitting, server-side rendering, and modularization.

The article has explored the benefits of independent development and deployment, seamless scalability, and the ability to rewrite parts of the system without overhauling the entire application. Micro frontends align with the advantages of microservices, enabling teams to work independently, develop rapidly, test easily, and deploy separately.

While the benefits are substantial, it is important to acknowledge the potential downsides of micro frontends. Maintaining consistent user experience across different systems can be challenging, but utilizing a design system can alleviate this concern. Making changes that span across the entire front end can be difficult, requiring isolated modifications to each part. Solutions such as mono-repositories, including the innovative turborepo, can facilitate coordinated changes across systems and mitigate repetition.

Overall, embracing micro frontends empowers organizations to revolutionize their front-end architecture, paving the way for the future of web development. By breaking free from monolithic applications and embracing modularization, businesses can unlock the power of micro frontends and unleash the full potential of their digital experiences


Top comments (0)