Micro frontends — My experiences and learnings
While working at Passei Direto in 2018, we decided to rebuild our angular monolith in Vue due to business and code issues. That was a challenging job, and I have several lessons that I would like to share with you.
Before the lessons, I want to explain how we divided our website (you can jump for the lessons if you want to).
App
It’s the project that contains the micro frontends. It serves to define the shared layout of the site (header and sidebar), to centralize the translations (importing from each micro frontend), to centralize the routes (importing from each micro frontend), and to define the version of each micro front end.
Lib of components
It’s the project that we put all the components we want to share with more than one project. It’s a critical part of the project that helps the teams work faster as we created a design system to share as many components as possible.
API services
On this repository, we centralize all our calls to API and apply mappers or any treatment for the data returned from the APIs.
Middlewares
All our middlewares are centralized on this repository.
Analytics
It’s where we have all the logic we need to do our analytics.
Checkout
The micro frontend responsible for the payment section of the website.
Onboarding
The micro frontend responsible for onboarding new users of the website.
Profile
The micro frontend responsible for dealing with all profile experiences of the user on the website.
User configurations
The micro frontend that allows the users to do all the configuration of their account on the website.
Home
The micro frontend that englobes the home page of the website.
Subjects
The micro frontend that enables the user to interact with our subjects (our website is a platform of study, because of that, we have a subject part).
Material viewer
The micro frontend that deals with our especial modal.
To be able to do the transaction between the Angular and the Vue parts during the development, we used Nginx reverse proxy.
Finally, let’s go to the lessons:
- It’s almost mandatory to create a lib of components to avoid replication of code and maintain a minimum of unique design;
- The lib of components it’s powerful, but “with great power comes great responsibility.” Imagine the problem of insert a bug in the button component. We learned to have extra care when modifying components here;
- It was a bad idea not to have documented the components of the lib of components because three teams were working on it, and sometimes one squad would build a component, and another would build something very similar, and no one noticed;
- Not having a documentation of the components led to spending more time to understand how to use a component and if a specific component already existed;
- The lib of component is critical because it can break parts of the website that the developer can not even imagine, so tests are super important here;
- Each project has the same folder structure, and this is very good for the developer to know where to find what they’re looking for;
- It was a great decision to split the page into modules, as exemplified above, so all the parts of the respective module were centralized in one place;
- We put a prefix per project in all SCSS classes to make it easier to trace which project generated that class;
- We used scoped CSS for our components. Before that was crazy to know which SCSS class was overwriting my class (even with the prefix);
- It isn’t easy to maintain the balance between a non-generic component and a very generic component;
- It was not a good idea to use an external library of components because we had to customize all components, which is risky. One thing that happened was that we updated the external library version, and it broke several customizations because they changed the names of their CSS classes. Now we only use the external library when the component it’s complex, and it’s not worth building from scratch because it would take too long for that;
- Dividing into micro frontends makes it easier to keep the code cleaner and more organized because it maintains only the context and what is needed for that part of the business;
- Dividing into micro frontends also allows each project to be deployed without compromising another part of the website;
- Vuex was essential to be able to sync the data between the projects efficiently. We also used namespace to dived better the store;
- Because we have a lot of micro frontends, new developers sometimes struggle to know where some code is;
- Another bad thing about having a lot of micro frontends is that you sometimes have to have a lot of visual codes opened to change all you need, and that can be very confusing;
- We have route lazy loading to decrease the bundle size, and this is good for the user;
- As we use the app project as the centralizer of all the other projects, we have to use the npm link to develop the features and see the change reflected in the app. Often this didn’t work as aspected (bugs everywhere), and we did not know why, resulting in deleting the node_modules, re-install and link all over again;
- We centralized all our shared enums in one project (API services) to not replicate code and avoid crazy bugs. It’s good for our sanity;
- We also centralized all our shared utils in one project (lib of components) for the same reasons of the enums;
- Dividing into micro frontends, it’s excellent if you have a lot of teams. Each team can take care of one project, and others squads don’t even have to see the code. It also avoids major merge conflicts.
You can check this article and others on my website: https://www.marinahaack.com/articles/Micro-frontends-%E2%80%94-My-experiences-and-learnings