iteratec Blog

Microfrontends: strategies for success

Written by Philipp Seßler | Aug 27, 2024, 10:00:00 PM

The right micro-frontend architecture can help teams work efficiently on complex web applications and respond flexibly to new requirements. However, there are numerous organisational and technical approaches to implementing microfrontends, and choosing the right strategy is crucial to their success. In this article, we provide an overview of the key approaches. 

 

What are microfrontends?

Microfrontends are an architectural pattern for web applications. They break down front-end interfaces into components that are developed and deployed independently, allowing developers to develop and update them in isolation.  

At iteratec, we focus on bespoke architectures tailored to our clients’ needs and the challenges they face. A modular approach using microfrontends can therefore offer advantages that help to reduce development times and simplify the maintenance and extension of the software with new features. 

Microfrontends can be implemented in various ways. A recommended article on this topic is ‘Micro Frontends’ by Cam Jackson, which explores some of the fundamental technical approaches. 

In this article, we aim to go beyond these basics and offer both more in-depth and broader perspectives. Using the differences and similarities between horizontal and vertical divisions of micro-frontends as a starting point, we will explain the various integration methods, their technical frameworks and their specific advantages and disadvantages. 

 

Organisation of microfrontends and teams 

Microfrontends are usually considered from a technical perspective in comparison to traditional monolithic web applications. However, this architectural pattern also offers significant organisational advantages. A key consideration here is exactly how microfrontends are structured and organised within an application – horizontally or vertically. 

Left: Horizontal division – several microfrontends are presented to the user simultaneously

Right: Vertical division – only one microfrontend is presented to the user at any one time 

 

Horizontal layout 

In a horizontal architecture, the user is presented with several microfrontends simultaneously. This architecture is particularly well-suited to feature teams: microfrontends focus on individual features, which are developed in parallel by independent teams.  

In a horizontal split, teams are grouped according to subject matter expertise rather than technical considerations. A microfrontend team is therefore usually also responsible for API development. Unlike component teams, feature teams do not have a dedicated ‘backend’ team. In an end-to-end approach, the focus is on the feature lifecycle, and the team bears full responsibility for all aspects of a feature. This is often beneficial for the user experience, as the team can develop a deeper understanding of how the feature works as a whole and is able to respond quickly to user feedback. 

Another advantage of the horizontal structure lies in the reusability of individual microfrontends, such as authentication, headers, footers or shared layout components. In an e-commerce store, for example, the search function can be provided as a microfrontend and integrated into various parts of the main application, which reduces organisational issues such as duplication of effort. 

 

Vertical division 

With vertical division, only one microfrontend is presented to the user at any given time, with routing between them taking place via the URL. This division is based on the classic architecture for web applications. The individual microfrontends can be developed relatively independently as standalone web applications using the appropriate architecture and technology. 

 

In contrast to horizontal partitioning, vertical partitioning can be implemented not only with feature teams but also effectively with component teams. Within these teams, responsibility for a given feature may be distributed amongst different teams. For example, one component team may be responsible for the API, whilst another team develops the front end. 

 

In an e-commerce store, for example, user management can be implemented as a vertically divided microfrontend by two component teams. User management is not displayed alongside other features of the store and must be explicitly opened by the user (in contrast to the search function mentioned earlier, which is distributed horizontally). User management is developed by two component teams – one team for the front-end and another for the corresponding API. Of course, development by a single feature team responsible for both the front-end and the back-end is also possible. 

For cross-cutting issues in implementation and design, the vertical division must find individual solutions, for example through provided libraries and clearly defined user experience guidelines. This also applies to the horizontal division; however, the latter often has an advantage here, as it is generally more focused on reusability. 

 

Making the right decision 

The decision between vertical and horizontal organisation is not always straightforward and requires careful consideration. Nor is it possible to make a general recommendation regarding feature versus component teams. In practice, one often encounters a compromise between the two approaches and rarely finds solutions that are consistently applied throughout. 

For a deeper understanding – particularly of which team topology is suitable for which micro-frontend architecture – Luca Mezzalira’s “Building Micro-Frontends” is a useful resource. It also explains clearly how concepts from Domain-Driven Design can be implemented with micro-frontends. 

Although there are many factors to consider and it is difficult to make a general recommendation, experience shows that the horizontal division of micro-frontends by feature teams is becoming increasingly prevalent, particularly in projects during the growth phase. Furthermore, from a technical perspective, the horizontal division is more interesting than the vertical division, as the latter relies much more heavily on more traditional web development techniques such as single-page applications. 

We will therefore focus more specifically on the horizontal division, the technical framework and the challenges involved in the following sections. 

 

Approaches to horizontal distribution 

A horizontal partitioning of micro-front-ends requires that independently developed front-ends be integrated. This can be achieved through three fundamental approaches: 

  • Build-time integration 
  • Server-side integration 
  • Client-side integration 

The main difference between these approaches lies in the point at which the microfrontends are embedded into the overall application. What these approaches have in common is that, from the user’s perspective, they enable a seamless and consistent web application. We compare the approaches below and provide some initial guidance on when each approach might be suitable. Among other things, we are interested in the following metrics: 

  • Time to First Byte (TTFB): the time it takes for the browser to receive the first byte of the response from the server. It is an indicator of server response time 
  • Largest Contentful Paint (LCP): The time taken for the largest visible element in the client/browser to load completely. It provides a good indication of when the main content of a page becomes visible to the user. 

These two metrics are important because they influence loading speed. A faster loading time ensures a better user experience, as users have to wait less and can interact with the page more quickly. 

 

Buildtime Integration  

With build-time integration, the microfrontends are embedded into the application during the build process. From the browser’s perspective, there are no separate microfrontends, as all necessary integration steps have already been completed. The microfrontends are treated as dependencies of the main application and do not differ significantly from other external dependencies, such as component libraries. 

Figure 1: The microfrontends are integrated into the main application as build-time modules during the development phase and are tightly bound to the application by a bundler during the build process. 

 

In practice, microfrontends are often provided as JavaScript modules, which are bundled together with the rest of the application code by a bundler such as Webpack or Vite. These are referred to as build-time modules, as they form part of the final bundled product. 

Specialised runtime techniques or libraries are therefore not required. However, there are supporting tools that can streamline the build process, such as a private NPM registry or services like bit.dev, which simplify dependency management for development teams. 

 

Build-time integration is particularly advantageous for projects where the composition of the microfrontends is not dynamic and where a high priority is placed on performance. For Time To First Byte, this approach can deliver the best possible result, as the server only needs to serve the finished bundle. However, care must be taken to ensure that the overall bundle size of the application is kept small – otherwise, the Largest Contentful Paint may suffer significantly. Particularly with larger applications, this can often only be controlled to a certain extent. In such cases, alternative integration approaches via the server or the client are recommended. 

 

Server-side integration 

Server-side integration goes one step further than build-time integration by deferring the composition of the application until the moment the server request is made. Various middleware solutions are used here, which act as template engines to integrate the microfrontends into a main application at runtime. If the integration is carried out at the level of the Content Delivery Network (CDN), this is often referred to as edge-side integration. The client remains unaffected by the composition. 

Figure 2: In server-side integration, the microfrontends are made available to the server. The server then uses a template engine to assemble them into a main application. The client is unaffected by this and sees only a single application. 

 

This approach places a greater load on the server than build-time integration and increases the time to first byte (TTFB). It is therefore advisable to use high-performance middleware or a template engine that efficiently renders the application and the requested microfrontends. 

Traditional methods such as Server-Side Includes (SSI) or Edge-Side Includes (ESI) are, despite their age, stable standards supported by many servers and CDNs, even though their implementation may vary depending on the provider or vendor. However, these techniques are often less favoured for new projects, as they no longer provide an ideal user experience for developers. Modern alternatives such as Podium, Isomorphic Layout Composer (ILC), Piral and Tailor offer more advanced but less widely adopted solutions. 

Compared to build-time integration, server-side integration allows for greater flexibility and scalability, as microfrontends can be deployed and updated independently of one another. 

For purely server-side integrations, the microfrontends to be displayed must already be included in the request to the server so that the server knows what to render. If the user is to navigate to a new microfrontend, a new request is required. In this case, the server delivers the entire application again, including those microfrontends that remain unchanged. 

This approach is therefore less suitable for interactive applications, as frequent server requests can impair the user experience. In practice, therefore, a combined approach involving client-side integration is often used.  

 

Client-side integration 

With client-side integration, the microfrontends are loaded individually in the browser and are therefore integrated into the application at the very last possible moment. This approach offers even greater flexibility than server-side integration and enables improved performance when routing between microfrontends, as only the modules currently required need to be loaded dynamically from the server. 

Figure 3: For client-side integration, the server makes the individual microfrontends available. These are retrieved by the client and embedded into the main application. 

 

As JavaScript code must first be executed on the client side for the integration, the LCP is potentially reached later on the first page load than with server-side integration.  

In practice, therefore, a combined approach with server-side integration is often used. In this approach, the server renders a static page containing all the microfrontends and sends it to the client. JavaScript is then executed on the client to activate interactive modules via hydration. Hydration refers to the process by which a statically rendered page is transformed into a fully interactive page through the execution of JavaScript. This technique enables the user experience to be accelerated by displaying the initially visible content quickly, whilst interactive features are loaded and activated as soon as the JavaScript is available and has been executed. 

There are two main technical approaches to implementing runtime integration: 

  • Client-side integration via iFrames 
  • Client-side integration via DOM manipulation
 

Client-side integration via iFrames 

iFrames represent a technically straightforward approach to integrating microfrontends. They work by loading standalone web applications within the same browser window as separate entities. iFrames provide strong isolation between the various microfrontends and feature numerous built-in security functions. 

Embedding iFrames generally does not require any specialised frameworks. Developers can use standard HTML and JavaScript techniques to integrate iFrames into their applications. However, iFrames have drawbacks that can severely limit their potential uses: 

  • Layout restrictions: iFrames do not support responsive behaviour in terms of automatically adjusting their height, which makes it difficult to create responsive layouts. 
  • Performance: Managing multiple iFrames can be resource-intensive for browsers. Extensive use of iFrames can therefore impair an application’s performance and lead to noticeable deterioration in the user experience. 
  • Accessibility and SEO: iFrames can have a negative impact on a page’s accessibility and search engine optimisation. They disrupt a page’s semantic structure, and search engine crawlers often index the content of iFrames as separate pages, causing the context of the embedding to be lost. 

Nevertheless, for many applications, the use of iFrames remains a valid and recommended approach. iFrames are particularly popular as a method of integrating microfrontends, especially in internal corporate applications subject to restricted layout and SEO requirements. iFrames are also popular in other contexts: for example, YouTube uses iFrames to embed videos on various websites.  

 

Client-side integration via DOM manipulation 

Unlike iFrames, client-side integration via DOM manipulation resolves many of the problems mentioned. The DOM (Document Object Model) is the internal structure of a website within the browser and allows for real-time manipulation via a JavaScript API. This API is used to integrate microfrontends into the website at the very last moment. 

Unlike build-time integration, which uses static build-time modules, microfrontends are provided here as dynamically loadable in-browser JavaScript modules. Each microfrontend acts as a standalone node in the DOM, which is added to an existing element of the main application at runtime. 

Figure 4: The main application is loaded by the client, including the JavaScript code. The latter loads the microfrontends at runtime and inserts them at the designated locations in the DOM. 

 

Compared with the iFrame method, which requires specialised iFrame elements, DOM manipulation allows virtually any DOM element to be used as an anchor – this is often done using div elements. Furthermore, with this method, microfrontends do not need to be designed as standalone web applications. 

There are a number of libraries and technologies that are popular for implementing this approach – including Single-SPA, Module Federation and Import Maps. For further reading on the technical aspects , *Micro Frontends in Action* by Michael Geers is highly recommended. 

 

Conclusion 

In this article, we have provided a comprehensive overview of microfrontends as an architectural pattern. We have compared various approaches, along with their advantages and disadvantages, which must be weighed up differently depending on the context and use case. However, there are also numerous other challenges that are common to all approaches. 

Although individual teams develop their microfrontends independently, ultimately someone must take responsibility for integration testing to ensure that all microfrontends work together seamlessly. Ensuring a consistent user experience across all microfrontends is equally important. 

At a technical level, it is essential to develop strategies for situations where individual microfrontends are unavailable. Furthermore, communication between the microfrontends, as well as numerous security aspects, must be carefully planned and implemented. 

Microfrontends offer enormous potential for designing applications in a modular and flexible way. However, one must be aware of the diverse challenges and the associated complexity. At iteratec, we understand these challenges and are happy to support you with our extensive experience and project expertise. 

Do you have any questions or require assistance?

You can find out more about microfrontends and bespoke software development on our website. Please feel free to get in touch with us.