Micro-frontends Using React: The Complete Guide
Micro-frontends entail the splitting of frontend monoliths into smaller, easier-to-manage pieces. This can improve the effectiveness and efficiency of front-end code.
Join the DZone community and get the full member experience.Join For Free
Frontend development comes with a lot of challenges. Finding ways to simplify the development process and accelerate the execution of tasks is the goal of every development team. Having team members collaborate on tasks when working on a large, complex product is extremely difficult. Thankfully, micro-frontends offer solutions to these challenges.
Micro-frontends entail the splitting of frontend monoliths into several smaller, easier-to-manage pieces. This development architecture is crucial as it can improve the effectiveness and efficiency of developers working on front-end code. This article will explore what micro frontends are with React and their benefits, downsides, implementation options, and micro-frontend architecture. We will also provide examples in order to help you grasp everything on a practical level.
What Are Micro-frontends?
Micro-frontends are a recent development pattern in which web application UIs are assembled from autonomous components.
These components can be built by different teams using different technologies. The architecture of micro-frontends is similar to that of backends, which are built using semi-independent microservices.
Over the years, micro-frontends have gradually gained popularity and acceptance in the developer space. Like microservices on the backend, each application (in micro-frontends) exists separately with a well-defined function or objective.
For example, a typical website has a Home page, About us page, Services page, Checkout page, Payment page, and more. According to the micro-frontends concept, each page can be developed as a single, autonomous application.
The software development teams can also be divided into specialized teams. Therefore, a team of developers can be responsible for writing the Home page, while another team is coding the Services page, and so on.
This approach comes with a lot of advantages. The micro-frontend architecture was designed to help engineers overcome challenges with the current SPA frontend development.
With this recent and trending front-end development approach, developers can simplify tasks, encourage collaboration, improve the effectiveness and efficiency of the process, and significantly increase productivity.
Brief History of Micro-frontends
In 2011, Microservices were explained during an event hosted for software architects. At the time, it was a development style many companies were experimenting with. With time, the benefits of Microservices became successful as a backend development architecture.
For evolution purposes, Thought Works came up with the term Micro-Frontends in Nov 2016, a frontend architecture similar to microservices. Companies, therefore, started experimenting with frameworks that could enable them to create frontends using the new architecture.
In Nov 2017, Single-Spa was recommended by Thought Works for micro frontend implementation. Next, in 2019, Martin Fowler wrote a popular article titled Micro-Frontend, which promoted micro-frontend architecture. In late 2020, Zack Jackson released Module Federation, a plugin included in Webpack 5.
The Module Federation revolutionized the micro frontend space. Organizations have now adopted the plugin to move problematic monolithic applications to the micro-frontend. That said, micro-frontends are still in their “infancy,” and we can expect to see more revolutionary changes.
How To Develop a Micro-frontend?
Having defined a micro-frontend and its brief history, let’s now explore different ways you can develop a micro-frontend. You can build a micro-frontend using the following three approaches:
- With Module Federation
- With Web Components
- With IFrames
1. Module Federation
Module Federation, a plugin by Webpack 5, enables you to develop various builds that are not dependent on one another. As a result, they can be built and launched individually. With the plugin, you can quickly create multiple functions to make up a single product.
What Makes Module Federation Interesting?
Some features make Module Federation worth considering for your development needs. Here’s why you should use it:
- Resolve Dependency Challenges: The plugin has functions allowing developers to resolve dependency issues.
- Great Code Sharing: It offers developers a better way to share code. Developers can expose any code for any application that Webpack supports.
- It isn’t Environment-dependent: You can apply shared code on diverse platforms. The fact that it’s not dependent on any environment eradicates any challenge related to incompatibility.
Module Federation Configuration
The plugin needs to be configured for appropriate use. You need to know how the configuration works to make the most of the software. Here are the major configuration options you need to be acquainted with:
- Name: This refers to the exclusive name of the exposed container. The name you input when initializing ContainerPlugin, used by Module Federation, becomes the container’s relative path.
- Library: The library is what dictates how the exposed code is stored and accessed. The library function allows you to further configure it in order to determine the name and type.
- Filename: This is the filename for the output bundle. In addition, it also functions as the bundle’s entry point.
- Remote: The remote configuration option has to do with the list of static remote modules. Local modules can access these remote modules.
- Shared: This configuration option enables you to share your node libraries. This option also comes with a range of configuration functions that enable you to determine how libraries are shared.
There are also other Webpack configuration functions you need to understand, including Output, Experiments, and Optimization. A good understanding of these configuration options is necessary to be able to properly develop a micro-frontend with Module Federation.
2. Web Components
Web components are low-level browser application programming interfaces that enable developers to extend the browsers using new components. In addition, web components offer a standard interface for defining or determining new components.
This tool is useful for contemporary web design and development, where developers leverage components to house user interface capabilities. With web components, you can develop components that utilize HTML and DOM API used by other front-end frameworks.
This implementation is interesting because you enjoy the flexibility of developing your own components without losing interoperability. Once you’ve built a web component, you can apply it in a wide range of applications since web components are functional wherever the web is functional.
The Three Main Concepts of Web Components
There are three concepts of web components you need to comprehend:
1. Custom Elements: These are JS APIs that enable you to build custom HTML elements. When developing your own HTML elements, you can dictate exactly how they behave.
2. Shadow DOM: This refers to a private DOM that is available only to your component. The shadow DOM is able to isolate JS and CSS.
3. HTML Templates: These are HTML tags you can use to build templates for your components.
IFrames allows you to implement micro-frontends. Basically, IFrames are HTML documents that can be incorporated into another HTML document. IFrames are embraced because they make it easy to develop a main page out of independent sub-pages. When it comes to styling and global variables not impacting one another, IFrames provide a reasonable level of isolation.
Although they are great overall, IFrames do have some downsides. IFrames are old technology old and, therefore, do not provide the best developer and user experience. Working with them entails certain difficulties that affect the responsiveness of your page. Nevertheless, IFrames can be used to develop microfrontends.
A leading advantage of IFrames is their ability to offer independence and a good isolation level among micro-frontends. This enables you to fully leverage the benefits of the micro-frontend architecture. On the flip side, they make it difficult to integrate micro-frontends with one another. Furthermore, IFrames lack flexibility and are hard to link and route.
Benefits and Tradeoffs of Micro-frontends
A micro-frontend is a new frontend architecture that resolves some of the major issues that come with the conventional monolith frontend architecture. In this section, we’re going to be taking a look at the advantages and disadvantages of micro-frontends.
Benefits of Micro-frontends
1. Incremental Upgrades: Adding new features to a large, old, monolithic frontend app can be both cumbersome and difficult. With micro-frontends, your team can quickly upgrade and deliver new features by breaking down the app into different pieces. Instead of approaching the frontend architecture as a single application, different parts of the application can be worked on and new features delivered separately.
This approach enables teams to apply incremental upgrades to dependencies, user experience, load speed, architecture, and more. Development teams can streamline their efforts to focus on a particular part of the product. This creates a platform for thorough decisions and high-quality implementation of new technologies – as opposed to having to approach one giant and cumbersome frontend app.
2. Simple Codebases: One of the challenges developers face is sophisticated codebases. Dealing with a complex codebase is a job of its own, seeing as you need to be extra careful in order to avoid mixing things up. You can put all this in the past with a micro-frontend. This new approach breaks things down into different, smaller code bases, thus providing the simplicity you need to code with optimal clarity.
By default, the code of each frontend app will be smaller than the monolithic code. Consequently, it’s easier to work with. In addition to offering a clutter-free codebase, proper boundaries are set between components. Developers are, therefore, less likely to get confused or frustrated trying to fix bugs or make changes to the code.
3. Independent Deployment: Micro-frontend enables independent deployment. Due to the existence of multiple frontend apps in separate builds, you can deploy each one individually. Regardless of where the code resides or is hosted, every micro-frontend is expected to have a development pipeline that enables you to build, test, and deploy.
The ability to deploy independently allows you to ship features much faster. For instance, when working with a monolith frontend app, you must wait until you have finished applying changes before you can deploy. With the micro-frontend approach, a separate part of the product doesn’t prevent you from deploying a part that’s ready.
4. Autonomous Teams: The modularity of a micro-frontend allows for a focus on a specific part of a product. If you have a big team, you can improve effectiveness and efficiency by dividing your team into smaller units. Each group of developers will be responsible for working on a given part of the product, thus improving focus and enabling engineers to build a specific feature with maximum efficiency.
Apart from encouraging specialization and improving the quality of the code being shipped, team management and collaboration are enhanced. Furthermore, it’s easier to know who does what when the team is small.
The team head will also find that task allocation and monitoring become easier – compared to bigger teams. Overall, autonomous, small teams create a comfortable space that promotes collaboration and skill transfer.
5. Tech Agnostic: Micro-frontend allows you to maintain each app as a module and separate them from others. As a result, you can develop each app using different technologies, frameworks, or libraries. The ability to diversify development technologies or frameworks allows you to build robust products using the best possible tools.
Every part of a product is different, and so are the tools required to build them. Instead of being stuck with a given set of frameworks, micro-frontends give you the flexibility to explore development tools pertaining to each module freely.
The Tradeoffs of Micro-Frontends With React
1. Bigger Download Sizes: Duplicate dependencies are reported to be the reason micro-frontends cause bigger download sizes. Given that every app is built with React and each has to download the dependency when a visitor wants to load a page, higher download sizes result.
For example, here’s how micro frontends React happens: a user has to download React more than once (multiple times) as they move from one page to another – given that every micro-frontend has a copy of React. This major architectural concept could significantly impact load time, affecting user experience and conversion rate.
However, individual pages still can load faster at the initial fast load speed. That said, subsequent navigation will be slower as users must reload the same dependencies as they move from one page to another.
2. Differences in Environment: It can be disastrous if the development container is different from the production container. The micro-frontend architecture enables developers to create separate frontend apps without being hindered by the micro-frontends being built by other development teams. This decentralized approach makes development faster and a lot easier.
However, developing in an environment that differs from the production environment comes with a serious problem. A micro-frontend will be broken or behave differently after deployment to production if the development-time container is different from the production container. A key sensitive part of this issue is the global style that could be part of the container or other micro-frontends.
The remediation process is simple. When building locally in an environment that behaves differently from the production environment, it is advisable to integrate and deploy micro-frontends to production-like environments regularly.
In addition, proper testing should be carried out regularly to ensure integration problems are spotted and fixed on time. This will go a long way to minimizing this potential tradeoff. You need to evaluate the risk of integration challenges for every project you intend to execute with micro-frontends.
3. Management Complexity: The micro-frontend decentralized approach usually leads to a complex range of small teams and resources that can be difficult to manage. Micro-frontends make for more things to handle. Depending on the size of a project, there will be more repositories, tools, development pipelines, servers, domains, and so on.
In light of the above, it’s advisable to consider the responsibility that comes with handling decentralized development architecture before adopting it. You need to have enough automation on the ground to be able to provision and cope with the proliferation of resources.
When it comes to managing a development process, using micro-frontends means that decisions concerning tooling and coding best practices will be more decentralized and will not be under the control of central management. Adapting micro-frontends requires the user to be comfortable with having less control over important decision-making processes.
4. Compliance Issues: Maintaining uniformity across many independent frontend codebases can be difficult. It takes excellent leadership to ensure quality, consistency, and governance are upheld across all teams. Compliance issues are bound to pop up if code review and regular supervision are not properly executed.
How To Build a Micro-Frontend With React?
Now that we’ve covered what a micro-frontend is, how it works, development approaches, advantages and disadvantages, it’s time to learn how to build a micro-frontend with React.
Step 1: Create the three modules: host, layout, and pages.
Step 2: Start with your layout components
Step 3: Create some pages
Step 4: Put everything together in the Host module
Step 5: Run the three apps and try each of them on your browser.
For the purposes of our example, we will be using a recipe website. Does Click and Cook sound like a cool name to you?
As we teach you how to build a micro-frontend, we will be making use of Webpack’s Module Federation with the help of create-mf-app in order to speed things up a little.
Steps Involved (We Are Going to Suppose the User is Using Linux/MacOS)
Step #1: Create the three modules: host, layout, and pages.
- Create the directory for the project and move into it.
- Mkdir micro-frontend-example && cd micro-frontend-example.
- Create a Host Module.
- Create the Layout Module.
- Finally, create the Pages Module.
Step #2: Start with your layout components (those that are commonly shared over all pages). Note: We will be using Tailwind to give the components some style.
- Create a Header component. Code:
- Create a Footer component. Code:
- Expose both components in a webpack.config.js file.
Step #3: Now, let’s create some pages!
- We will need some routing, so let’s start by installing a react router on all modules.
- `npm install react-router-dom`.
- Next, let’s add some fixed recipes to a JS/JSON file.
- Now, create a page to list all recipes.
- Create a page to show the details of a single recipe.
- Expose both components in the webpack config file.
Step #4: Put everything together in the Host module.
- Add both Pages and Layout Modules as remotes in the webpack.config.js file of the Host Module.
- Add the components and routes to App.tsx.
Step #5: Run the three apps and try each of them on your browser.
- Run the `npm start` command in each one of the modules and then go to localhost:3000 to test the result!
Note: To see the full example, go to GitHub.
Micro-frontends are undoubtedly a revolutionary architecture that solves some of the problems associated with monolith frontend apps. With a micro-frontend, you can enjoy a speedy development process, improved efficiency, incremental upgrades, simple codebases, independent deployment, autonomous teams, and more.
Before adopting the micro-frontend architecture, make sure to consider the automation requirements, operational and governance complexity, quality, uniformity, and other important factors.
Published at DZone with permission of Alfonso Valdes. See the original article here.
Opinions expressed by DZone contributors are their own.