Microfrontends

Microfrontends

GatsbyJS’s Founder Kyle Mathews made a profound observation recently, stating that, "Websites today are still made the same way they were 20 years ago, with a cumbersome monolithic approach to building sites, storing data, and delivering content. It’s time for a new way to build the web."

This led me to think our current architectural approach to web development. The need for a new model was apparent - today's projects are becoming increasingly complex, and the bundle size of JavaScript is expanding. This is not only increasing the initial load time whenever a user types a URL but also leading to several other issues.

For instance, some features are effortlessly developed in specific frameworks or libraries, but in others, it becomes a complex task. This calls for an architectural paradigm that is library or framework-agnostic, thus allowing all frameworks and libraries to co-exist harmoniously.

These challenges led to the development of a new architecture inspired by microservices, thus giving birth to the concept of microfrontends.

Looking back through the progression of this evolution:

Initially, we had monorepos where all the mobile, web, and other apps were stored in the same place. Over time, the monolithic architecture was adopted, where the frontend application was stored, managed, and developed independently. The backend team then followed suit with their own backend tasks. Next came the concept of microservices architecture where the backend team was divided into different teams based on feature development. Each team would work in isolation and deploy their code independently. This triggered a desire to achieve a similar architecture on the frontend. As a result, frontend developers started dividing large complex applications into smaller ones, based on the features they provide, and build them individually. This enabled all the teams to better understand and be responsible for the features they were building the UI for. See below to understand that evolution.

Microfrontends evolution

So, what is microfrontend? We can define it as the extension of microservices in the world of frontend or the decomposition of a monolithic frontend app into smaller, independently deployable components.

We've now discussed how to segregate microfrontends, but we still need to integrate these different microfrontends into one container or shell. To do this, there are two approaches:

  1. Build time integration
  2. Run time integration

In build-time integration, we develop the app, deploy it, and publish it as an npm package to the npm repository. It's then installed as a dependency in the shell micro frontend and built there. The issue with this approach is that we need to build the shell application again to reflect any deployed microfrontend.

In run-time integration, we deploy each microfrontend at a URL like www.xyz.com/app1. In the shell micro frontend, we can fetch the hosted microfrontends with the help of module federation(webpack) and display it in the shell.

Here's how to implement it:

First, you need to expose the app or component at the microfrontend by placing the component path in the expose attribute in the webpack.config.js file.

plugins: [
	new ModuleFederationPlugin({
		name: "mfe1",
		filename: "remoteEntry.js",
		remotes: {},
		exposes: {
			"./mfe1": "./src/App.jsx",
			"./header": "./src/Header.jsx",
		}
	})
],        

In the shell application, we need to add the exposed microfrontend paths in remotes.

plugins: [ new ModuleFederationPlugin({ name: "shell", filename: "remoteEntry.js", remotes: { "mfe1": "mfe1@https://localhost:9001/remoteEntry.js>", "mfe2": "mfe2@https://localhost:9002/remoteEntry.js>" }, exposes: {}, }), ]


Then, we can easily import the microfrontend app or components of microfrontends in the shell application. This is a simple example of how to inject microfrontend 1 and microfrontend 2 into a shell application.

import React from "react";
import ReactDOM from "react-dom";

import "./index.css";

import MFE1 from "mfe1/mfe1"
import Header from "mfe1/header"
import MFE2 from "mfe2/mfe2"

const App = () => (
  <div className="container">
    <div>Name: shell</div>
    <div>Framework: react</div>
    <div>Language: JavaScript</div>
    <div>CSS: Empty CSS</div>
    <div>
      <div>
        <Header />
        <MFE1 />
      </div>
     <div>
        <MFE2/>
     </div>

    </div>
  </div>
);

export default App;
        

With the help of module federation, we can now easily integrate microfrontends. To establish communication between the microfrontends, we can use a variety of strategies, such as local storage (though that might seem like a funny suggestion), centralized state management like Redux, custom events, or a custom message bus.

Here is a GitHub repo where I've implemented microfrontends in a simple and easier way. You can clone it and follow the steps mentioned in the readme file to see the microfrontends in action.

The key advantages of using Microfrontends are:

  1. Individual teams can work on microfrontends in isolation.
  2. Each micro frontend can use a different framework of their choice.
  3. Deployment is faster.
  4. Bug fixes, patches, or framework updates can be applied individually without affecting other apps.
  5. It improves scalability.

Disadvantages of using Microfrontends:

  1. Data sharing and establishing communication between the microfrontends can be difficult.
  2. You need to configure CI/CD for every microfrontend.
  3. You might encounter duplicate dependencies as each microfrontend has its own.
  4. Testing the integrated part of microfrontends is challenging.
  5. Tracking the team's efforts can be difficult.
  6. The initial setup can be time-consuming.
  7. If not properly managed, it could put extra load on the shell or container server.

To wrap things up, microfrontends are definitely a game-changer, in my opinion. They may seem a bit tough to handle at first, but once you get the hang of them, you'll see how they can help make work smoother, faster, and easier across different teams.

Still, just like everything else in web development, microfrontends aren't perfect. They have some tricky parts we need to tackle, like setting up and managing dependencies. But hey, we're no strangers to a good code challenge, right? If we plan it right and understand the ins and outs, we can make the most out of microfrontends for our projects.

So, let's embrace this new way of building web apps, learn more, and push the boundaries of what we can achieve in web development.

Luiz Felipe Cirqueira dos Santos

Docente, Pesquisador e Desenvolvedor Fullstack | Php, Laravel, C#, .Net, .Net Core, asp.Net, Java, Javascript, NodeJs, Typescript, Nextjs, Reactjs, React Native e Vuejs

2 个月

I invite you to participate in this form, which is part of the scientific research for my master's dissertation. Your responses will be essential to the success of this study. You consent to share the information provided by completing and submitting the form. I thank you in advance for your valuable contribution. https://forms.gle/2KXna2KbQp71Jgj39

回复

要查看或添加评论,请登录

Siva Rajana的更多文章

社区洞察

其他会员也浏览了