Increasing Agility in Microfrontend Design: A Developer’s Guide



This content originally appeared on Bits and Pieces – Medium and was authored by Ashan Fernando

Looking at different techniques to increase agility in Microfrontend design

Microfrontends (MFEs) break down complex frontends into smaller, manageable pieces. On the surface, MFEs look like a silver bullet for scaling front-end teams. But in reality, you will face new challenges requiring advanced techniques to tackle them.

One of the primary concerns is the impact on the agility of design, development, and architecture. How can you maximize the agility MFEs promise?

This post explores techniques and best practices, ensuring your team can move quickly to leverage MFEs effectively.

Why Agility Matters

Agility in software development is a necessity. Most of you have experienced how agility is compromised when software development teams scale in size. Two main reasons affect agility.

  • The size of the code base affects the cognitive ability of developers to work with code.
  • Bottlenecks in increased communication and collaboration.

So, the obvious solution is to break the code base into smaller pieces and put large teams into smaller teams. Looking at the surface, that's what MFEs do for the front end. It offers a unique opportunity to keep your development teams small and effective regardless of the size of your frontend codebase.

Agility is not an option, but a necessity in today’s fast-evolving digital landscape.

MFEs give teams the autonomy to push updates independently. This independence is crucial for innovation, enabling teams to deploy new features and fixes quickly.

Balancing Between Autonomy and Coupling

Autonomy in MFEs is a double-edged sword. While it allows teams to work independently, the final product should be consistent in design.

Maintaining a consistent user experience across different MFEs is essential. In simple terms, from the eyes of end-users, MFEs don’t exist (not visible).

Though sharing code between MFE teams is discouraged in favour of autonomy, some elements, like the design system, must be shared across all MFEs to ensure uniformity.

The Architecture of a Modern Frontend Design System

For example, consider a large-scale e-commerce platform where different teams manage the product listing, shopping cart, and user profile sections. Each team can develop and deploy features independently, but the overall look and feel must remain cohesive. Sharing a design system becomes imperative.

Why Autonomy Matters: Autonomy is vital for rapid development. Teams can release features quickly When they are not dependent on each other. For instance, the team handling the shopping cart can introduce a new checkout feature without waiting for updates from the product listing team, significantly accelerating the development cycle.

Components to Simplify

Components for MFEs

Component-based development enhances agility in MFEs. By building applications with reusable components, teams can streamline collaboration and sharing. Bit, a platform for managing and sharing components, facilitates this process. With Bit, components can be developed, shared, and maintained independently, fostering collaboration.

One unique advantage of using components is that MFE teams can now share components beyond the Design System. Since each component has its lifecycle, governance rules and practices can be implemented to avoid conflicts and tight coupling.

For example, if a different MFE team finds a bug in a component belonging to another, they can fix the issue and send a Merge Request only for the component, where they can go through an approval process similar to pull requests in Git. This controlled sharing ensures quality and consistency while allowing flexibility.

Dependency Handling

Effective dependency management is crucial for maintaining agility in MFEs. While internal dependencies are usually manageable, external dependencies can create challenges, especially when different versions are involved.

Visualizing dependencies can help users understand the impact of a component change, especially when they cross beyond an MFE team's boundary. Following is an example of Bit’s dependency graph.

Dependency Graph of Components

It clearly visualises component dependencies, helping teams manage and control them effectively.

For example, consider an update to a shared component impacting several MFEs. With Bit’s dependency graph, you can quickly identify all affected components and plan the updates accordingly, maintaining agility while ensuring stability. You can even inform the other MFE teams that depend on it.

Yet, other MFE teams have full autonomy since they can decide when to use the latest component version.

What about third-party dependencies?

Third-party dependencies have several impacts on MFEs. If each MFE uses different versions of the same third-party dependency, each may have to bundle it alongside it, causing the effective bundle size to go up.

Besides, when a security issue is found, it may need to be patched as soon as possible, regardless of whether it cuts across MFE boundaries.

Therefore, it requires MFE teams to establish complete governance over third-party dependencies.

One common strategy is to use a package proxy to monitor security and track third-party dependencies across MFEs.

Use of Peer-Dependencies

Understanding peer dependencies is also vital. Each MFE might depend on certain framework or core library versions that need to be compatible. For example, if one MFE uses React 17 while another uses React 18, it could increase bundle sizes and decrease performance.

Using Peer Dependencies can eliminate this issue where each MFE depends on a base React version outside its context to be available for it to run.

Understanding Peer Dependencies in JavaScript

Managing these dependencies ensures a smooth and performant user experience.

Runtime vs Build Time

The choice between runtime and build-time integration significantly impacts agility. Runtime integration allows for more flexible and faster releases since it doesn’t require a complete build for every change. However, it poses testing challenges as changes aren’t verified until runtime.

For example, using runtime integration, you can deploy a new feature to a specific part of the application without rebuilding the entire front end, enabling rapid iteration and quick feedback cycles. However, thorough testing is necessary to catch issues early.

On the other hand, build-time integration ensures that issues are detected and addressed before deployment. While this approach can increase the overall build time, it provides higher reliability and consistency.

Bit Components: Build Time and Runtime Consumption

Imagine multiple teams working on a feature spanning several MFEs. Using build-time integration, you can test the entire feature end-to-end before deployment, reducing runtime issues and optimizing the entire application bundle.

Understanding these factors is important to optimize the MFE architecture so teams can maintain agility in different parts of the frontend lifecycle.

Developer Experience (DX)

Maintaining a high level of Developer Experience (DX) is crucial for productivity and agility. Developers need an environment where they can quickly develop and test code, with short feedback loops enhancing efficiency.

Ensuring a robust DX helps teams deliver high-quality updates faster, fostering an agile and responsive development culture.

Developers should focus on the code they need to modify without dealing with a massive codebase, which is one motive behind moving to MFEs.

DX with Components
This experience can be amplified when building MFEs with Bit, where the recognizable modification unit becomes a component.

Besides, ensuring a robust DX involves having proper testing frameworks in place. Automated testing, including unit, integration, and end-to-end tests, should be part of the development workflow. This ensures that changes can be verified quickly and reliably, maintaining high-quality standards while enabling rapid iteration.

Conclusion

Increasing agility in Microfrontend design involves balancing autonomy with consistency, managing dependencies effectively, choosing the right integration strategy, and maintaining a high DX. By adopting these techniques, developers can leverage the full potential of Microfrontends to innovate and release quickly, delivering superior user experiences while maintaining control and quality.

By focusing on these areas, developers can create an agile and responsive development environment that supports rapid innovation and high-quality delivery.

Whether you’re working on a small team or a large-scale project, these principles will help you harness the power of Microfrontends to achieve your development goals.

Thanks for Reading! Cheers!

Learn More


Increasing Agility in Microfrontend Design: A Developer’s Guide was originally published in Bits and Pieces on Medium, where people are continuing the conversation by highlighting and responding to this story.


This content originally appeared on Bits and Pieces – Medium and was authored by Ashan Fernando