Micro-Frontends With React & Vite Module Federation

Rate this content
Bookmark

From my experience one of the hardest things is to share information between microfrontends, so in this talk I would like to explain various ways on how to share a design system to ensure uniformity to the application. Another difficult thing is sharing dependencies, fortunately with module federation it can be done, but how can I use different versions of the same library and how does it work behind the scenes?


I'm the creator of module-federation/vite library, with React and this library, I'd like to show you how you can achieve these results by configuring everything correctly.

20 min
23 Oct, 2023

Video Summary and Transcription

Microfrontends is an architecture used by big companies to split monolithic frontend applications into manageable parts. Maintaining a consistent look and feel across different microfrontends is a challenge. Sharing styles can be done through Vanilla CSS, CSS modules, or CSS in JS. JavaScript variables can be used in styles, but readability and runtime overhead are considerations. Sharing state in microfrontends can be achieved through custom events, broadcast channels, shared state managers, or custom PubSub implementations. Module federation with Vite allows for client composition and sharing dependencies. Configuration is similar to Webpack, and future work includes working on the QUIC framework.

Available in Español

1. Introduction to Microfrontends

Short description:

Microfrontends is an architecture that allows us to split a monolithic frontend application into multiple microfrontends. We can have vertical splits, where each microfrontend is responsible for a specific page or multiple pages, or horizontal splits, where different teams manage different parts of the application. This architecture is used by many big companies to easily manage their frontend codebase. Even if you have a small application, you can use microfrontends to gradually replace parts of your legacy application. However, one challenge is maintaining a consistent look and feel across different microfrontends.

Hello, everybody! Welcome to this talk, Microfrontends with React and Module Federation with Vitz. I would like, with Microfrontends... I know that this is a React Advanced Conference, but I would like to share with you Microfrontends architecture for those that don't know really well into deep the architecture.

So, Microfrontends is more or less what is microservices, but for the front-end. If we have a monolith, we can split the server part in microservices to manage better the endpoints and also the features, but in this particular case, the front-end is a monolith. So we can slice the monolith, the front-end monolith into many microfrontends, and that's more or less the architecture. We can have multiple vertical domains, so we can have one frontend in React, one another in Angular, and for example, another in Vue. And theoretically, microfrontends is both, so the server part and also the frontend part. But how we can slice the monolith? So we can slice our application, frontend application, into different ways.

We have a vertical split, so one microfrontend for each page or multiple pages. The blue team is looking for the homepage, and the red team is managing the checkout. Or we can split in a horizontal way. The blue team is the owner of the menu and the app bar, and the red, the green and the red is managing the dashboards. So this is more or less how we can split the monolith in vertical and in horizontal. But do we need, do I need this type of architecture?

These are some of the companies that are using micro frontend, and as you can notice, these are big companies. So this architecture is born to divide the frontend application and manage easily the codebase into multiple teams. But if I have a mid or a small application, I can use this concept, this architecture for the Strangler partner. So if I have a legacy application, I can replace pieces of my application to renovate it. So if you have an house and you want to, for example, renovate your garden, you can rip off all the old garden and put a new one. So that's more or less the idea that we can apply to our legacy application. So there are a lot of challenges in this process. One of them is the look and feel. So here you can see it's a modern house. So if we go into this modern house, we visit a little bit the location. We can see the kitchen that is a modern kitchen. We can go to the living room. But if we go to the bathroom, and we go into the bedroom, and we see this different style, it's a little bit weird. So you can imagine this concept in our application. We go into the home page, and it's really cool. We go into the product page, and it's cool as well.

2. Managing Styles in Microfrontends

Short description:

We need to share a style through the whole application to avoid different styles in different parts. We can use Vanilla CSS and inject style sheets, but we may face clashes. To avoid clashes, we can use npm package post CSS prefix wrap or post CSS prefixer for Vite. Another approach is to use CSS modules or CSS in JS, which allows locally scoped styles and easy management.

We go to the checkout, and we can see a completely different style. So our look and feel of the application need to be the same to avoid this kind of problematic or odd situation. So we need to share a style through the whole application, but how we can share these styles?

So we can use Vanilla CSS. So we have Microfrontend A and Microfrontend B. We can simply inject the style sheet inside of the page and we can define two classes, card title. So Microfrontend A has a card title with the color black and we have Microfrontend B with the same name with a color red. At the end, if we inject in this specific order the style sheets, we have the result is card title red, because the last CSS win override the other. So how we can avoid in this kind of situation this problem?

We can use npm package. This is for webpack, is post CSS prefix wrap. Basically, what is doing, is wrapping our CSS and put a prefix for all the CSS to avoid this clashes. It's quite used, more than 19,000 of download, weekly download in npm. But if your application is in Vite, you can use post CSS prefixer. As you can see here, we are defining the selector, and the output is prefix underscore underscore selector. So, it's wrapping for us in the building process, it's wrapping the CSS and giving us a possibility to define a CSS without clash other CSS from other micro frontends.

We have an independent possibility to define our class and use them. Or we can use another way is to use CSS modules. So, we can define this kind of type of file, so card.module.css, we define our CSS, so card background color black. Then we can import this module.css into our React component. And we can use this object styles.card. So, this card is basically our CSS, we can inject into the JSX of our React component. And the build process output will be more or less like this. So, card this is the name of the module. Card is the main name of the CSS. And we have this unique ID that avoids clashes through the other CSS. And this is locally scoped. So, we don't have a problem with other cart properties, cart CSS into the other files.

Another way to manage the style is CSS in JS. It's locally scoped style, like the CSS model we saw before, so we avoid clashes. It's a good approach for the co-location because we can co-locate the CSS into our JavaScript file or TypeScript file, so into our React component. The CSS is really nearby our component, so it's easy to manage the style and the other things.

3. Using JavaScript Variables in Styles

Short description:

You can use JavaScript variables in styles, making it convenient to use specific variables for padding or other purposes. However, there are some costs associated with this approach. The core code readability becomes more challenging, especially when using CSS modules, as the specific hash used in CSS modules requires inspecting the DevTool to understand the CSS better. Additionally, CSS in JS adds runtime overhead to the application.

You can use JavaScript variables into styles, so if you have a specific variable for padding or whatever, you can use this variable into the CSS and it's really handy. There are some costs. The core code readability, like the CSS module, in the DevTool of Chrome, or your browser, it's a little bit difficult, because if you remember in the CSS module, we have this specific hash, so we need to look into the DevTool to understand better our CSS. And this specific CSS in JS adds runtime override. So when our application is running, it's adding a little bit of a read for our application.

4. Sharing State in Microfrontends

Short description:

To share the state in microfrontends, we can use custom events, broadcast channels, or a shared state manager like ZooStand. However, it's important to share as little information as possible to avoid coupling the microfrontends. Another option is to create a custom PubSub implementation, but it may introduce dependencies between microfrontends and rely on the window object.

Another big problem to solve in this kind of architecture is to share the state. So we have multiple ways to share the state. So we can use a custom event. So one microphone tends to call custom events, and another one is listen to it. This is a really basic implementation, and we are using Vanilla API of the browser. So it's really good. We can use broadcast channel. And this approach allows us to use Win, pass the information through Windows, tabs, iframes. So if we have some iframes, it's a really nice approach.

We can have a share state manager. So for example, we can have a ZooStand state manager. And we can share the instance of this ZooStand through our microphone tense. Keep in mind that in your architecture, you need to share as less as possible information, because you can share like the theme or other things. But don't share too much because the basic approach for micro frontends is to the couple, the deploy and also the development. So if you share too much with other micro frontends, of course, you are coupling the micro frontends, and it's difficult to end up with this problem.

So we have the last possibility so we can have custom PubSub implementation, so we can create our own implementation for managing the state through our micro frontends. So here is a small snippet. I grabbed this small snippet from this article from my friend Florian Rappel. So thanks. I would like to share and look at this snippet with you. So this is the code from the shell, the app shell that is loading all the micro frontends. So we are defining in the window a publish function, a subscribe function and unsubscribe function and then we have 11 listeners for PubSub. In the micro frontend A we can basically subscribe to this topic micro frontend A, and in the micro frontend B we can publish something to this specific topic. So if we call window.publish, we are dispatching an event with detail and topic and message. With this particular trick of a variable we are calling at the end the topic handlers because the window.subscribe() here is saving all the message function. So when message arrives, someone publish something into a topic, into the topic handler we are looping to all these topic handlers and we are calling the function. So finally at the end of this process, microfrontend A is able to get their information. I don't like too much this implementation, it's a simple implementation and you can start from it, that's why I decided to put this a snippet into the slides. I don't like because microfrontend B need to know, let me say, that there is another microfrontend and as we mentioned before, we would like to decouple as much as possible our process. And another thing that I don't like too much is the window object, so we are using the window as a shared object through all our architecture.

5. Client Composition with Module Federation and Vite

Short description:

In this talk, we'll explore client composition using module federation with Vite. Module federation allows us to share dependencies and create a more modular architecture. With the release of the open-source module federation model by Zach Jackson, we can now use module federation with Vite. I created a library for module federation with Vite, which can be used with various frameworks. The implementation of Vite module federation is similar to the Webpack one, allowing for mix and match usage. To use module federation with Vite, you need to define a special configuration and await the federation function.

But as I mentioned before, for starting a minimum approach and then we can add the feature and another feature, it's really cool.

Okay, so we can composite this architecture in many ways. We can composite the architecture into the server side, so the server is grabbing all the information and it's creating our application for us because at the end, the application is always one, so the end user go through one application. And we can have also the edge, edge composition, so to the Lambda or CDN, we can composite all the micro-frontends and we can have client composition.

So in this talk, I would like to go into the client composition and for client composition, we have a module federation. So we have a Webpack. And in August 2022, Zach Jackson, the I think the main guy that is looking for module federation, release the open source, this specific model. So I work in pair programming with my friend, Manfred Steyer. And with this particular possibility that Zach Jackson gave us to the open source, the library, we create the possibility to do a module federation with Vite. So the other main bundler out there. So Manfred created this native federation layer. So it's a layer of a native API, and create also the angular implementation on top of this layer. I created a more general purpose module federation Vite. And you can use this library for Svelte, React, Vue or whatever. And so now module federation, we can use module federation with Vite as well. So this is really, really awesome. I created this library in my GitHub profile. And Jack Jackson saw my work and decided to move all the code into the module federation organization. So if you go into the module Federation slash Vite, you will find this plugin. You can find also the implementation for React and many other framework. So I archive my project and I move all the code there. So how we can share the dependencies. So another big thing into the architecture is to share the dependencies. And fortunately, the implementation of Vite module Federation is really similar to the Webpack one. So the original one. So you can mix and match module Federation with Vite and module Federation with Webpack. And you need to define for Vite, you need to define a configuration, a special configuration so you can await the federation function. Because a plug-in in Vite are more or less a function. You can grab this function from module Federation slash Vite. You can and you need to define configuration and few other options.

6. Configuration and Future Work

Short description:

This configuration is similar to the Webpack one. You can define a name, expose the component to share with the main application, and share libraries. By sharing libraries, you can avoid downloading the same code base multiple times and reuse the cached version. In this case, we keep react-dom/server and server.node. I'm a FoodStack developer for clarinet, an open source developer in my free time. I'm currently working on QUIC framework and believe it will be a great framework for the future.

And what is this configuration? This configuration is really, really similar to the Webpack one. So you can, this is a configuration for a remote. that is loaded from our shell application. So you can define a name, you can expose the component that you would like to share with the main application. So this is your micro front end basically. And you can share also the libraries. So here we are sharing all our libraries, but you can define one by one a specific library. So if two micro front ends need the same library and the same version, we can avoid to download twice the same code base, but we can reuse the only one that we are in cache. And basically we can keep some other library that we don't want. So in this specific case, we keep react-dom slash server and server.node.

Okay. That's all. I'm a FoodStack developer for clarinet. You can find me on X, and my handle is at georgio underscore boa. Or you can find me on LinkedIn with my name and surname. I'm an open source developer in my free time. And currently I'm working hard on QUIC framework. Since 2022 I work with QUIC. I'm core maintainer collaborator. I'm pushing in the core code base as well. So if you would like or if you are interested in looking to QUIC, please have a look because I think it will be great framework for the future. Thank you for listening and have a nice conference.

Check out more articles and videos

We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career

JSNation Live 2021JSNation Live 2021
31 min
Vite: Rethinking Frontend Tooling
Top Content
Vite is a new build tool that intends to provide a leaner, faster, and more friction-less workflow for building modern web apps. This talk will dive into the project's background, rationale, technical details and design decisions: what problem does it solve, what makes it fast, and how does it fit into the JS tooling landscape.
Remix Conf Europe 2022Remix Conf Europe 2022
23 min
Scaling Up with Remix and Micro Frontends
Top Content
Do you have a large product built by many teams? Are you struggling to release often? Did your frontend turn into a massive unmaintainable monolith? If, like me, you’ve answered yes to any of those questions, this talk is for you! I’ll show you exactly how you can build a micro frontend architecture with Remix to solve those challenges.
React Advanced Conference 2023React Advanced Conference 2023
33 min
React Compiler - Understanding Idiomatic React (React Forget)
Top Content
React provides a contract to developers- uphold certain rules, and React can efficiently and correctly update the UI. In this talk we'll explore these rules in depth, understanding the reasoning behind them and how they unlock new directions such as automatic memoization. 
React Advanced Conference 2022React Advanced Conference 2022
22 min
Monolith to Micro-Frontends
Top Content
Many companies worldwide are considering adopting Micro-Frontends to improve business agility and scale, however, there are many unknowns when it comes to what the migration path looks like in practice. In this talk, I will discuss the steps required to successfully migrate a monolithic React Application into a more modular decoupled frontend architecture.

Workshops on related topic

React Day Berlin 2022React Day Berlin 2022
86 min
Using CodeMirror to Build a JavaScript Editor with Linting and AutoComplete
Top Content
WorkshopFree
Using a library might seem easy at first glance, but how do you choose the right library? How do you upgrade an existing one? And how do you wade through the documentation to find what you want?
In this workshop, we’ll discuss all these finer points while going through a general example of building a code editor using CodeMirror in React. All while sharing some of the nuances our team learned about using this library and some problems we encountered.
JSNation Live 2021JSNation Live 2021
113 min
Micro Frontends with Module Federation and React
Workshop
Did you ever work in a monolithic Next.js app? I did and scaling a large React app so that many teams can work simultaneously is not easy. With micro frontends you can break up a frontend monolith into smaller pieces so that each team can build and deploy independently. In this workshop you'll learn how to build large React apps that scale using micro frontends.
JSNation Live 2021JSNation Live 2021
113 min
Micro-Frontends with Module Federation and Angular
Workshop
Ever more companies are choosing Micro-Frontends. However, they are anything but easy to implement. Fortunately, Module Federation introduced with webpack 5 has initiated a crucial change of direction.
In this interactive workshop, you will learn from Manfred Steyer -- Angular GDE and Trusted Collaborator in the Angular team -- how to plan and implement Micro-Frontend architectures with Angular and the brand new webpack Module Federation. We talk about sharing libraries and advanced concepts like dealing with version mismatches, dynamic Module Federation, and integration into monorepos.
After the individual exercises, you will have a case study you can use as a template for your projects. This workshop helps you evaluate the individual options for your projects.
Prerequisites:You should have some experience with Angular.