Micro frontends in the MailUp Platform

Micro frontends are a means to add new functionalities to the platform, or to modify an existing one. They enable the freedom to adopt new technologies and new languages.

Rudy Bozzetti
Growens Innovation Blog
5 min readJul 28, 2020

--

The problem

At MailUp we needed to reimplement two significant sections of our application within a limited timeframe; however, no one was keen on using the existing technologies.

The current application is a consolidated product and it has existed for many years. It was built as a monolithic application, which many people are uncomfortable with. Nonetheless, it has some advantages:

  • single codebase: all the code is in one place
  • consolidated CI/CD: build and deployment pipelines are ready, tested, up and running since time
  • all-in-one solution: editing, building and code debugging with a single tool

And, of course, some disadvantages:

  • it’s a mix of older technologies: it’s a .NET Framework project that includes some pages made with AngularJS (Angular 1.x). The support for this framework is close to its end.
  • difficult to update: trying to update the core framework is difficult considering the number of parts that may need to be adapted to the new one. Yet, at the same time the project continues to grow
  • long development and testing times: given the technologies involved, a considerable amount of time elapses between when a change is ready and when it can be tested, both on our workstations and development servers
  • vendor lock-in condition: we are tied to a vendor’s developer workstation OS, server OS, application servers and development tools.

The solution

The solution identified involves the use of micro frontends. The micro frontends approach allows you to break down a single web project into a series of separate and independent functionalities, effectively extending the same ideas behind microservices to the frontend world.

Each single feature can be developed, tested, released and maintained independently. Developing these different functionalities gives you the freedom to try new approaches and new technologies.

There are some definite drawbacks to this approach or, at least, aspects that require careful consideration:

  • UI/UX consistency: when developing in different environments, the different functionalities must be coherent and maintain the same aesthetics
  • Authentication/authorization coherence: the different micro frontends — even working independently — must be able to recognize a user who is accessing the entire application and apply the same restrictions or authorization rules
  • Integration and communication: it is necessary to develop a way to integrate the different micro frontends in the main application. In addition, micro frontends may need to communicate with each other
  • Code duplication: addressing similar issues in the various micro frontends, code duplication is very likely.

Another reason we decided to adopt micro frontends is that we could not afford a complete rewrite of the entire application in a single release.

Our solution

Our approach was to create “small” Single Page Applications that deal with specific sections of the main application, essentially served as static HTML/JS/CSS resources and easily deployable on the cloud.

So we evaluated different JavaScript frameworks and finally decided to use React.

Our motivations were as follows:

  • It is a “lightweight” solution
  • It has a reasonably fast learning curve
  • It has a reliable owner and is supported by a large community

We decided to build our own shared component library in order to reduce code duplication, have a common user interface and reuse CSS rules already written for the main project. This library has a dedicated repository and is included as a dependency in the different micro frontend projects.

We use Storybook inside this library. This allows us to immediately view and test the various components that we are going to implement. In addition, this is useful for documenting and sharing our work with other teams.

Integration was quite straightforward and is based on iframes, as they were already in use in the main project.

Difficulties and compromises

Authentication was one of the initial issues we had to deal with. The main application manages the identity of the connected user via cookies but these are not reusable in the micro frontends as they reside in different domains. We therefore decided to generate an OAuth2 token on the main application and then pass it to the various micro frontends through an onboarding phase before invoking the required functionality.

As for the shared component library, we decided to initially use the same CSS used previously. It was a good compromise in the initial phase as it allowed us to immediately have a seamless user interface with the rest of the application. However, we plan to review this aspect and to look for a more modern CSS-in-JS style solution, without giving up the consistency rules already established.

Another important aspect to consider is the application state management. React is basically a presentation library that renders a user interface from a state, but about the management of this there is full freedom.

One of the evaluated options was to adopt Redux; however, it seemed too complex and perhaps not necessary for the current logic of our micro frontends. Therefore we decided to use Context API and Hooks, basic functionalities already present in the most recent versions of React.

The adoption of this technology has also enabled us to learn many new tools such as node and npm for JS dependency management and webpack for bundling resources. It has also allowed us to make intensive use of the CLI, which was unusual for some team members.

Plus points

On a positive note, this experience was an opportunity to (re)learn JS and use it in a completely different way than we did with jQuery and AngularJS. It was a chance to think about all the new features introduced from ES6 onwards such as native Promises, async/await, arrow functions, etc.

This led us to become more familiar with functional programming, which allows us to write functions that are also easy to test, or to handle immutable data, which makes the state of the application more manageable.

The development of a shared library has led us to build a series of truly reusable and self-contained components.

This environment is OS-agnostic and independent of the used tools. This allowed us to collaborate with people who employed different tools and operating systems from ours without encountering any compatibility issues.

Finally, the creation of test and deployment pipelines was also quite easy and straightforward.

Conclusion

Developing these new sections by implementing micro frontends was a positive experience, and one that has enriched our knowledge.

Three things to consider:

  • Is the size and maintainability of your application starting to be a problem?
  • Do you want to develop new features or review existing ones?
  • Do you want to isolate new projects as much as possible?

If so, a micro frontends approach could be the best solution.

--

--