Frequently Asked Questions

Micro Frontends: Concepts & Implementation

What are micro frontends?

Micro frontends are an architectural approach where large frontend applications are broken down into smaller, manageable pieces that individual teams can build, deploy, and maintain independently. This concept is similar to microservices on the backend, but applied to the frontend, allowing for modularization and scalability. (Source)

Why use micro frontends instead of a monolithic frontend?

Monolithic frontends can become difficult to maintain as the codebase grows, leading to challenges with upgrades, dependency management, and team coordination. Micro frontends solve these issues by splitting codebases, teams, and responsibilities vertically, reducing coupling and allowing teams to manage their dependencies and tech stacks independently. This results in faster development, easier upgrades, and more scalable applications. (Source)

What are the main advantages of micro frontends?

Key advantages include incremental upgrades (teams can update parts of the app independently), simple and decoupled codebases (smaller, less cluttered code), independent deployment (each micro frontend can be deployed separately), and independent teams (each team can own and manage their part of the application end-to-end). (Source)

What are the disadvantages or challenges of micro frontends?

Micro frontends introduce additional operational costs and complexity, such as more infrastructure requirements, more CI/CD pipelines, and potential dependency duplication. Poor architectural decisions early on can be costly, and user experience may suffer if dependencies are not managed wisely, as users may need to download more data. (Source)

How do micro frontends work in practice?

Micro frontends are typically implemented by building and deploying each part of the frontend separately, then integrating them at runtime (not build time). Tools like Webpack Module Federation allow teams to pull in components from different micro frontend apps dynamically, enabling independent development and deployment. (Source)

How do micro frontends compare to backend microservices?

Micro frontends are similar to backend microservices in that both approaches break down applications into smaller, manageable pieces with low coupling. Each team can independently develop, test, and deploy their part of the application, improving scalability and flexibility. (Source)

What is an example of implementing micro frontends?

An example implementation involves creating separate apps (e.g., a Home app and a DoctorProfile app), each running on different ports and managed by different teams. Using Webpack Module Federation, components from one app (like DoctorProfile) can be dynamically loaded into another (like Home), allowing for independent development and deployment. (Source)

What are best practices for implementing micro frontends?

Best practices include building and deploying each micro frontend separately, integrating components at runtime (not build time), and using tools like Module Federation to manage dependencies. Good system design is crucial to minimize coupling and avoid costly architectural mistakes. (Source)

Hygraph Features & Capabilities

What features does Hygraph offer?

Hygraph offers a GraphQL-native architecture, content federation, scalability, and a wide range of integrations (including Netlify, Vercel, Shopify, AWS S3, Cloudinary, and more). It also provides enterprise-grade security, intuitive user interfaces, and robust API capabilities. (Source, Integrations)

Does Hygraph provide an API?

Yes, Hygraph provides a powerful GraphQL API for efficient content fetching and management. (API Reference)

What integrations are available with Hygraph?

Hygraph integrates with platforms such as Netlify, Vercel, Shopify, BigCommerce, AWS S3, Cloudinary, Bynder, Mux, Scaleflex Filerobot, Lokalise, Crowdin, EasyTranslate, Smartling, Ninetailed, AltText.ai, Adminix, and Plasmic. (Integrations)

How does Hygraph ensure performance and scalability?

Hygraph is optimized for rapid content delivery, which improves user experience, engagement, and search engine rankings. Its architecture supports scalable, responsive content distribution, reducing bounce rates and increasing conversions. (Source)

What security and compliance certifications does Hygraph have?

Hygraph is SOC 2 Type 2 compliant, ISO 27001 certified, and GDPR compliant. It offers features such as SSO integrations, audit logs, encryption at rest and in transit, and sandbox environments to protect sensitive data and meet regulatory standards. (Security Features)

Use Cases & Customer Success

Who can benefit from using Hygraph?

Hygraph is ideal for developers, IT decision-makers, content creators, project/program managers, agencies, solution partners, and technology partners. It is especially beneficial for modern software companies, enterprises modernizing their tech stacks, and brands looking to scale across geographies or re-platform from traditional solutions. (Source)

What industries are represented in Hygraph's case studies?

Hygraph's case studies cover industries such as food and beverage (e.g., Dr. Oetker), consumer electronics (e.g., Samsung), automotive (e.g., AutoWeb), healthcare (e.g., Vision Healthcare), travel and hospitality (e.g., HolidayCheck), media and publishing, eCommerce, SaaS (e.g., Bellhop), marketplace, education technology, and wellness and fitness. (Case Studies)

Can you share some customer success stories with Hygraph?

Yes. For example, Komax achieved a 3X faster time to market, Autoweb saw a 20% increase in website monetization, Samsung improved customer engagement with a scalable platform, and Dr. Oetker enhanced their digital experience using MACH architecture. (Customer Stories)

How quickly can Hygraph be implemented?

Hygraph is designed for rapid implementation. For example, Top Villas launched a new project in just 2 months from the initial touchpoint. Customers can get started quickly by signing up for a free account and using available documentation and onboarding guides. (Documentation, Top Villas Case Study)

Pain Points & Solutions

What problems does Hygraph solve?

Hygraph addresses operational pains (reducing reliance on developers for content updates, modernizing legacy tech stacks, resolving global team conflicts, improving user experience), financial pains (lowering operational costs, speeding up time-to-market, reducing maintenance costs, supporting scalability), and technical pains (simplifying development workflows, streamlining query management, resolving cache and integration challenges). (Product Page)

How does Hygraph solve pain points for different personas?

For developers, Hygraph reduces boilerplate code and streamlines query management. For content creators and project managers, it offers an intuitive interface for independent content updates. For business stakeholders, it lowers operational costs, supports scalability, and accelerates speed to market. (Product Page)

What KPIs and metrics are associated with the pain points Hygraph solves?

Key KPIs include time saved on content updates, system uptime, content consistency across regions, user satisfaction scores, reduction in operational costs, time to market for new products, maintenance costs, scalability metrics, and performance during peak usage. (CMS KPIs Blog)

Pricing & Plans

What is Hygraph's pricing model?

Hygraph offers a free forever Hobby plan, a Growth plan starting at $199/month, and custom Enterprise plans. For detailed pricing and feature breakdowns, visit the pricing page.

Support & Getting Started

How easy is it to get started with Hygraph?

Getting started is straightforward: sign up for a free-forever account, and use resources like Hygraph Documentation, video tutorials, and onboarding guides. Even non-technical users can begin using Hygraph right away, thanks to its intuitive interface. (Documentation)

What support and training does Hygraph provide?

Hygraph offers 24/7 support via chat, email, and phone. Enterprise customers receive dedicated onboarding and expert guidance. All users have access to detailed documentation, video tutorials, webinars, and a community Slack channel. (Contact Page)

How does Hygraph handle maintenance, upgrades, and troubleshooting?

Hygraph provides 24/7 support for maintenance, upgrades, and troubleshooting. Enterprise customers benefit from dedicated onboarding and expert guidance, while all users can access comprehensive documentation and community resources. (Contact Page)

Company & Vision

What is Hygraph's vision and mission?

Hygraph's vision is to unify data and enable content federation, empowering businesses to create impactful digital experiences. Its mission is to remove traditional content management pain points through a GraphQL-native architecture, helping businesses modernize their tech stacks and deliver exceptional digital experiences at scale. (About Us)

Blog & Resources

Where can I find more resources and documentation about Hygraph?

You can access comprehensive technical documentation, developer tutorials, and the latest updates on the Hygraph Documentation and Hygraph Blog.

Webinar Event: How to Avoid Personalization Tech Traps

Micro Frontends - A Complete Guide

Micro Frontends is a concept of breaking huge frontend applications into smaller and manageable pieces.
Aagam Vadecha

Written by Aagam 

May 19, 2022
micro frontends

#What is it & Why Micro Frontends?

Micro Frontends is a concept of breaking huge frontend applications into smaller and manageable pieces that individual teams can build and maintain. If you understand microservices for the backend, it is similar, just applied to the frontend. Let’s go over the concept first.

To explain the frontend microservices, we first have to define the monolith. In a monolith system, everything resides in one repository and all the developers work on the same code base. For every single change, the entire app needs to be built, tested & shipped as a whole. In a lot of cases, this approach is fine, it works if you do it right and a lot of systems use it efficiently. However, as the software scales, there might be a need for a more efficient solution and a full rewrite might seem tempting.

In the early stages of building monoliths, it's likely for developers to unintentionally introduce high couplings where they otherwise wouldn’t exist, and when the project scales, the team size increases, many issues may arise. It becomes difficult to upgrade the dependencies due to a big codebase with huge impacts, a lot of time would be spent in coordination between developers, testing and deployments become slower, individual changes cannot be shipped, slowing down the pace of the team bringing value to the clients.

However, with microservices or micro frontends, codebase, teams, and responsibilities are split vertically in a way that the coupling between them is very low. Each team owns a smaller codebase, and can individually test, deploy and scale according to the needs. Now the teams only need to coordinate for the moving parts, which can be kept minimal with a good system design. The teams can easily manage their dependencies and even use a separate tech stack.

Let's back it up with a backend example so that everything fits right in!

Consider a very general backend monolith that contains all the core product APIs, all the code to generate pdfs, manage image resizing & uploads, sends notifications from a job queue, and a common database. These kinds of codebases cause the issues mentioned earlier.

Instead, if we break down all these services into different backend apps altogether, each deployed and maintained by individual teams, it's going to be much easier and faster to develop, maintain and ship even as the app scales. For example, for a team that works on and maintains the code to generate PDFs, the only thing the other teams need to know is the API contract. The core product might be written in Node, the PDF team can choose Python and a separate database even and it would be just fine. If with time, the demand for generating PDFs increases, we can scale only the PDF service horizontally instead of scaling the entire backend app in case of a monolith. Lastly, if you start looking properly you will definitely be able to form boundaries and split the core product APIs even into separate services and databases.

This concept of splitting up a monolith has already proven to be a great success in the backend and is picking up pace for frontend apps as well.

#Advantages Of Micro Frontends

Incremental upgrades

With a frontend monolith that’s armored with an outdated tech stack, developers are generally under the notion, If it works, don’t touch it. They need to make upgrades, but it’s a bit scary as the scope and impact are too wide. So either the upgrades happen with careful planning and a lot of work or they’re delayed till a point of absolute necessity. Micro frontends divide the scope of a single monolith, which in turn allows teams to easily make their upgrades as and when they see fit.

Simple, decoupled codebases

A monolith has a lot of code that keeps on increasing with time. On the contrary, the source code for micro frontends would be much smaller, which is a big relief. Additionally, devs would have less clutter on the screen every time they open up their project. Also, just like microservices, micro frontends would lead us to create proper boundaries between apps and in the process force us to avoid all couplings which might unintentionally exist in monoliths.

Independent deployment

Similar to incremental upgrades advantage, micro frontends also reduce the scope of deployments. All decoupled codebases should have their own CI/CD pipelines, the teams can individually decide if their app is ready to go in production and if it is, no issues from other apps would affect it. Also, with monoliths, for a small change or fix in some part of the app, you need to bundle all the code and ship it. Monoliths have long-running build & test phases in pipelines, but with a micro-frontend, you would simply have to ship just that app where the fix is needed.

Independent teams

Since we have decoupled codebases and independent deployments, the teams can own that app end-to-end. The teams can have full ownership of their deliverables. Just a side note, in many projects with monoliths, the frontend team tends to structure by a technical expertise filter.For instance, one team will handle all the layout & markup-related work, one will handle all the logic-related work, and one will do the CSS detailing & animations. This setting might not work, in micro frontends, each team needs to have all developers of Layout, Logic, CSS detailing capabilities.

#Disadvantages of Micro Frontends

In Software Engineering, tradeoffs are inevitable and everything has a price. You get the above benefits with micro frontends, but there are some drawbacks as well. You need a good architect to design a micro frontend architecture because design mistakes in early architecture can prove to be costly. With micro frontends, the operational cost and effort will increase, there will be more infrastructure requirements, more ci/cd pipelines, more domains, etc, compared to monoliths. Finally, there will be dependency duplication across different micro frontends. The user experience might suffer if the development team is not managing the dependencies wisely, as the end-user will have to download more data via network calls.

#Quick Recap

Monolith vs Micro FE

#How Do Micro Frontends Work?

There are many approaches that you might stumble across to implementing micro frontends, I’ll elaborate on the most common one that works and is used by many teams.

Wireframe image.jpg

Most frontends look something like this, wherein there is some common container with a header/footer/sidebar combination and changing content in between with layers of complexity. We can implement the container as one micro frontend app, and the rest of the content pages can be individual micro frontend apps in themselves.

Let’s look at the dependencies in package.json of the container app:

{
"name": "@portfolio/container",
"dependencies": {
"@portfolio/experience":"1.0.0",
"@portfolio/skills":"1.0.0",
"@portfolio/contact":"1.0.0",
...
}
}

Here we make a package out of each page, publish it, and then include it in the base app and use it. If the experience app needs to reuse some component of the skills page, then it can include skills in its package.json, the coupling can be managed via an API contract.

Well, this is a common misconception for many developers and is not the micro frontend approach. Let's say your skills app 1.0.0 is in use by the container and the experience app. It undergoes an upgrade and a 2.0.0 version is now published. However, you’ve built and deployed the experience app and the container app already with the skills 1.0.0 version. In order to use the 2.0.0 skills app, you’ll need to upgrade the skill package version in both experience and container apps, build and redeploy both apps. This defeats the purpose of micro frontends being individually deployable. We should not be integrating the pieces at build time but at run time.

#Implementing Micro Frontends & Best Practices

As mentioned earlier, the core technique to implement micro frontends is that we build & deploy everything separately and at run time we pull in the other components to use. At a very high level, it's like making a network call to get the component at the runtime via Javascript, and then using it. If we can pull in the actual skill component javascript itself from some server via a network call, it can give us the latest copy, unlike a package that has already been bundled. To implement this from scratch might seem a bit complicated, Module Federation simplifies building micro frontends. So let us get our hands dirty, build an example app and see a practical implementation of the concepts we talked about!

#Awesome Doctors!

If you stumble somewhere along the path, the final working code is here. We’ll make a small frontend app that shows a list of doctors and if you click on one of them it redirects you to a doctor’s profile. The aim here is to understand how micro frontends work in practice and form a decent base upon which you can build further.

Move to a fresh folder and let's call it the root folder. We have a nice utility to use module federation, so type npx create-mf-app The CLI will ask you a few questions regarding your framework choice and then set up a boilerplate, name this first app home. Open another terminal in the same root folder and create one more app with npx create-mf-app and name it doctorProfile. Start this app on a different port. I’ll be using React with Tailwind and running the apps on ports 4000, 4001 respectively. Go to both folders individually, install all packages and also install react-router-dom and then do a yarn start.

Note: It’s possible after the yarn install, the apps might give you an error regarding a memfs package, just install it as well.

StartApp1.jpg

StartApp2.jpg

So now we have two different apps, running on different ports. Let's move forward and do all the basic stuff in individual apps.

Home App

We will need some data to work with, for simplicity we’ll create a dummy file to act as our API src/service/doctorService.js

const doctorList = [{
id: 0,
name: "John Doe",
fees: "100$",
speciality: "Physician"
},
{
id: 1,
name: "Mary Jane",
fees: "150$",
speciality: "ENT, Dermatologist"
}, {
id: 2,
name: "Jane Doe",
fees: "200$",
speciality: "Pulmonologist"
}]
export const getDoctors = () => {
return doctorList
}

We’ll create some super simple components.

src/components/Header.jsx

import React from 'react'
import { Link } from 'react-router-dom';
function Header() {
return (
<div className="p-4 bg-gray-900 text-white flex justify-between items-center">
<Link to="/">
<span className="text-2xl font-bold" >
Awesome Doctors
</span>
</Link>
</div>
);
}
export default Header;

src/components/Footer.jsx

import React from 'react'
function Footer() {
return (
<div className="p-4 bg-gray-900 text-white text-sm">
All Rights Reserved.
</div>
);
}
export default Footer;

src/components/DoctorList.jsx

import React, { useState, useEffect } from 'react';
import { getDoctors } from '../service/doctorService';
const DoctorList = () => {
const [doctorList, setDoctorList] = useState([])
useEffect(() => {
setDoctorList(getDoctors())
}, []);
return (
<div className="flex flex-col flex-1 items-center justify-center">
{doctorList?.length > 0 ?
doctorList.map((doctor) => {
return (
<div className="w-2/5 flex flex-col mb-4" key={doctor.id}>
<div
className="bg-gray-800 rounded-lg p-5 mb-1 cursor-pointer
hover:shadow-lg transition-all"
>
<div className="uppercase text-base text-white"> {doctor.name} </div>
<div className="flex justify-between">
<div className="text-sm text-gray-400 "> {doctor.speciality} </div>
<div className="font-bold text-gray-200"> {doctor.fees} </div>
</div>
</div>
</div>
)
}) : <div className="text-white"> Loading... </div>
}
</div>
);
}
export default DoctorList;

src/App.jsx

import React from "react";
import ReactDOM from "react-dom";
import Header from './components/Header'
import Footer from './components/Footer'
import DoctorList from "./components/DoctorList";
import { BrowserRouter, Route, Routes } from 'react-router-dom';
import "./index.scss";
const App = () => (
<BrowserRouter>
<div className="h-screen flex flex-col bg-gray-50">
<Header />
<div className="my-8 flex-1 flex">
<Routes>
<Route path="/" exact element={<DoctorList />} />
</Routes>
</div>
<Footer />
</div>
</BrowserRouter>
);
ReactDOM.render(<App />, document.getElementById("app"));

Check the browser, you should see a nice doctorList page!

CompletedApp

Cool! Our first app is ready! Now let’s go ahead and set up our other app.

DoctorProfile App

Note: These service files are for simplicity and to reduce the scope of this example, In a real app the requests will be made to an API server which will get consistent data from DB.

src/service/doctorService.js Add the same array here we did in the Home app and replace the function with:

export const getDoctorById = (id) => {
return doctorList[id]
}

src/components/DoctorProfile.jsx

import React, { useState, useEffect } from 'react';
import { getDoctorById } from '../service/doctorService';
import { useParams } from 'react-router-dom';
const DoctorProfile = () => {
const [doctor, setDoctor] = useState(null)
const { id: doctorId } = useParams()
useEffect(() => {
setDoctor(getDoctorById(doctorId))
}, []);
return (
<div>
{
doctor ?
<div className="bg-gray-800 rounded-lg w-96 h-96 flex flex-col items-center justify-center">
<div className="uppercase text-xl text-white"> {doctor.name} </div>
<div className="text-sm text-gray-400 "> {doctor.speciality} </div>
<div className="font-bold text-gray-300"> {doctor.fees} </div>
</div>
: <div className="text-white"> Loading ... </div>
}
</div>
);
}
export default DoctorProfile;

src/App.jsx

import React from "react";
import ReactDOM from "react-dom";
import DoctorProfile from './components/DoctorProfile'
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import "./index.scss";
const App = () => (
<BrowserRouter>
<Routes>
<Route path="/doctor/:id" element={<DoctorProfile />}>
</Route>
</Routes>
</BrowserRouter>
);
ReactDOM.render(<App />, document.getElementById("app"));

A quick check path /doctor/:id will give you DoctorProfileBase

#Micro Frontends In Action

Okay, so now we have two apps, running on different ports, one has our base with the doctorList and the other has doctorProfile. But we don’t want this, we want for the end-user to get a unified view of the system. We need to somehow bring the doctorProfile component in our base app, and to do that module federation will help us!

Inside the webpack.config.js we have the Module Federation plugin configuration, let’s use that. Go to the webpack.config.js of the DoctorProfile App Change the first four keys of the module federation plugin config to

{
name: "doctorProfileApp",
filename: "remoteEntry.js",
remotes: {},
exposes: {
"./src/components/DoctorProfile": "./src/components/DoctorProfile.jsx"
},
...
}

Go to the webpack.config.js of the Home App,

{
name: "homeApp",
filename: "remoteEntry.js",
remotes: {
doctorProfileApp: "doctorProfileApp@http://localhost:4001/remoteEntry.js",
},
exposes: {},
...
}

Okay, so what are we doing here? We exported the doctorProfile component from the DoctorProfileApp by adding an entry in the exposes setting, it will be exposed on the remoteEntry.js file on the DoctorProfile app server. After that, we added the same remoteEntry.js as a remote in the Home App’s webpack.config.js. Now restart both servers!

We can now use the DoctorProfile component in the Home App.

src/App.jsx

...
// Add this import
import DoctorProfile from "doctorProfileApp/src/components/DoctorProfile"
...
//Add this route
<Route path="/doctor/:id" element={
<div className="flex flex-1 items-center justify-center">
<DoctorProfile />
</div>
}/>
...

src/components/DoctorList.jsx

...
//Add this import
import { useNavigate } from 'react-router-dom';
//Add this function
const navigate = useNavigate();
const navigateToDoctorProfile = (id) => {
navigate(`/doctor/${id}`)
}
...
// Attach a click event with the a <div> tag to navigate to DoctorProfile page.
onClick={() => navigateToDoctorProfile(doctor.id)}
...

That’s it, Check the browser!

CompletedApp

CompletedApp2

We are now getting the doctorProfile components on the http://localhost:*4000*/doctor/2 path.

Also, to confirm the network call happening at runtime to fetch the remote component, open the Network tab in the Home App & reload the page. You can see network calls for getting the doctorProfile component happening on the fly. Try to make a change, for instance, the background color in the doctorProfile component in the doctorProfile App and then simply reload the home app, it will be reflected there as well (On Run Time, we won’t need to rebuild any apps).

NetworkEvidence

RunTimeEvidence

We have successfully implemented a small example of Micro Frontends!

If you want to go on to explore micro frontend patterns more, you can try going a step further. At times, it's not possible to avoid a shared state between micro frontends and you might need to manage it. And, the next step would be to build an app to manage some shared state.

For instance, you can develop this existing setup further to build a favorites app. that will manage favorite doctors. Place Add, Remove buttons in the doctorList but manage the state (i.e the list of favorite doctors) in the new favorites app and also keep that state in sync with the Home app so that you can make a decision whether to show the Add or the Remove button.

Something along these lines:

ExploreFurther1

ExploreFurther2

I’d recommend you to try on your own, you’ll need a library to manage observables something like Redux / Mobx / rxjs, and the learnings from this article, If you struggle you can always take a sneak peek here.

Blog Author

Aagam Vadecha

Aagam Vadecha

As a Software Engineer, my daily routine revolves around writing scalable applications with clean code & maintaining them. In my spare time, I love to explore software architecture patterns, write tech articles & watch thrillers!

Share with others

Sign up for our newsletter!

Be the first to know about releases and industry news and insights.