How do Frontend Microservices work?
We’re all aware that microservices have exploded in popularity lately, but unfortunately, this popularity takes place mainly in the backend. Many organizations are using this architectural style to avoid the limitation of large, monolithic backends. But, on the other side, many companies are struggling with large and complex frontend monolithic apps.
Lately, we’re seeing that the micro frontends are getting attention too. We’re seeing more and more design patterns and architectural styles for decomposing frontend monoliths into smaller, simpler chunks that can be developed, tested and deployed independently, while still appearing to the customer as a single cohesive product.
The challenge is escaping from monolithic apps and creating/using a more sophistic way for creating the client side of web application.
Why would we go forward with an initiative to escape from monolithic apps? Well, there are plenty of reasons for us to do so.
What I mean is that using micro frontend, we can achieve more in this direction.
With micro frontend, the life of a developer has become easier on some parts of the job that include: upgrading, updating, or even rewriting parts of the frontend (client) more smoothly than was previously possible. Also, it’s easier to ensure that the rest of the application will remain stable because each part (micro frontend) of the app is independent. The scaling of the app & team problem, in the standard way of developing apps is solved with micro frontends, due to the fact that for each micro frontend, a single team is responsible. This makes everything easier and more flexible.
In order to avoid developers from stepping on each other’s toes, and providing them an opportunity to be free and independently build, deliver, and choose their own tech solutions, we tend to go forward and implement the micro frontend pattern as much as we can.
As I have already shared some information on how micro frontends can make developers’ life’s easier, I would now like to talk about the Container, which is an important part of micro frontends.
In traditional SPAs, the whole app is developed in a single repository, sharing a common state management library, and optimization of bundle size is done by lazy loading various chunks based on different routes.
This approach is completely fine when the app itself is small, but when it starts to get bigger in size and becomes messy, then, it becomes challenging. For this reason, implementing micro frontends seems to be a good solution, but it also has its challenges. Unlike backend microservices, our frontend microservices still need to be rendered on the same window, and the whole app still needs to work seamlessly like one single unit.
To achieve that, we need an app (Container) that could manage individual micro apps lifecycles; downloading, mounting and unmounting the UI as well as provide communication medium between apps in addition to share data and a mechanism to render some common UI elements that will be shared across the whole app.
There are a number of ways to implement the micro frontends. I will go ahead and mention 4 of them.
1. Runtime integration (client-side composition)
This one is one of the most flexible approaches that developers are getting familiar and comfortable mostly. The idea here is to include each micro frontend onto the page with a <script> tag, and upon loading time, it exposes a global function as its entry-point. The container application then determines which micro frontend to be rendered, and then calls a function which directs a micro frontend when and where to render itself.
2.Build time integration
As we know, nowadays, the most of the code is implemented with this approach. The container will install its components as libraries that we install from npm. Anyhow, this approach has its downsides too. That includes the syncing of different versions of libraries, the different types of built problems, and the final size of the package will be big because of all dependencies that it contains. It’s also important to mention that it is a tight coupling between the container and its micro-frontends.
3. Run time integration via web components
Another approach to run time integration is implementing the micro frontends via web components. With this approach, each micro frontend defines an HTML element for the container to represent an instance, rather than defining a global function for the container to call.
4. Run time integration via IFrames
One of the simplest method to implement microservices, is using IFrames. By their nature, they make it easier to build webpages out of independent sub-pages. Using IFrames provides us with a good isolation in terms of styling and global variables, not interfering with each other.
Even though IFrames are not brand new technology (a fact that could make them sound less exciting) big companies such as Spotify use this approach to implement micro frontends. It also has its advantages and drawbacks.
Some of the advantages are:
- technology isolation,
- deployment isolation,
- runtime isolation,
- Shared branding and identity,
- Easy cache management,
- Smooth user experience.
Some of the disadvantages are:
- The loading time (which is slow)
- No code reuse
Some key benefits that you can get from micro frontends are:
- Better scalability;
- Faster development, as teams can work independently. This benefit, however, is applicable only if your project is big and has more than one front-end team;
- You can use multiple frameworks in your application. However, it should be done mindfully and transparently to avoid confusion. Nevertheless, you have a choice of what to use for a particular task. What’s more, a development team can choose their own technology;
- Deployment independence. The delivery of your micro frontend will not affect the entire application. The changes will affect precisely that part of the business process that it has covered;
- With micro frontends, you can upgrade, update, or even rewrite parts of the frontend more smoothly than was previously possible;
- It’s easier to ensure that rest of the app remains stable, as it’s independent. With micro frontends, you no longer need to keep track of the whole app. A team reviews a specific micro frontend, which has been changed or expanded;
- Codebases are smaller and more manageable;
- Easier hiring of experts. With micro frontends, you look for professionals to work on a specific part of an app where a particular tech stack is used, so you do not need them to know technologies that other teams use;
- Easier testing, as you test just separate features;
Some of the disadvantages you can get from micro frontends are:
- Complex testing of the application as a whole. Now that your application dynamically loads content, it can be harder to have a complete picture of the application. Each front end can be tested in isolation, but getting a real-world user test is critical to ensure the application works for the end-user. You can utilize usual black-box end-to-end testing with tools like Selenium or Cypress, as it’s agnostic to the implementation details;
- The wide variety of standards you have to keep up with. The application is broken into smaller parts; thus, it can be challenging to keep all developers working off the same standards. Keeping everyone on the same page is essential to delivering a high-quality user experience;
- Adopting micro frontends is a good idea for your business if your project is big and has more than one front-end team. With a small team, it is not worth the struggle;
- The deployment, assembly, and configuration process for each micro frontend will be different, which requires additional effort.
Nevertheless, you can overcome all these challenges by following the best practices.
So, is it worth it?
It all depends on the project that you’re working on. If it is a big project with a lot of UI elements and a lot of different views, then it is worth to give it a try!
But, if you’re developing a company website, or any other small website, then maybe you shouldn’t bother at all.