Choose your favorite theme for this reading:

Micro Frontends Patterns

The software industry, through the Software Engineering study field presents the concept of pattern inspired by what other mature fields were already doing, as Building or Hardware Engineering. There was a need to document successful practices, identify recurring issues and their solutions. A pattern, in simple terms, is a way of documenting these scenarios to mainly enable the reuse of strategic decisions involving the elements of a system. Patterns are not theoretical constructs but artifacts discoverede in more than one existing system. In recent decades, several authors have made great efforts to catalog patterns, which previously only resided in the minf of experienced developers. In this way, Design Patterns were lauched, and many software and systems around the world were able to benefit from this knowledge [Rising 1998].

[Jackson 2019] cataloged five possibilities for implementing Micro Frontend architecture as approaches. These approaches are already observed in practice in the software industry, and they can also can be classified as Micro Frontend patterns given their definition. The author also notes that, for all of those approaches, there is a need for a container application that takes care of:

  • Display common page elements, such as header and footerç
  • Address issues that cross the borders of “micro applications”, such as authentication and navigation;
  • Gather the N Micro Frontend applications on a single page and indicate where each one should be displayed.
The container application is highlighted with blue and shows the navigation and the “search” micro frontend highlighted with green. Source: [Jackson 2019].

The five approaches cataloged by [Jackson 2019] are described below.

  1. Server-side template composition
  2. Build-time integration
  3. Run-time integration via iframes
  4. Run-time integration via JavaScript
  5. Run-time integration via Web Components
  6. Module Federation

Server-side template composition

The template composition pattern on the server side is the most classic way of creating Micro Frontends (MFEs), which has been practiced even before this concept was formalized. In this pattern, there is a main page that loads the container application in the document index.html.

In addition to common elements, such as header, navigation menu and footer, the container application contains instructions for dynamically adding content through server variables. On the Web server, it is possible to define that a variable is filled with a value informed through the requested URL. Thus, the variable is filled with a block of HTML delivered by the requested micro frontend application, forming a complete page for the end user (as illustrated in Figure 1).

The HTML block can belong to a dedicated team, which treats it differently from other parts of the complete system. The HTML block can have its own construction, testing and deployment process and, therefore, not affect other areas. In this pattern, the possibility is still suggested for the team to have its own server, with careful caching of responses to prevent latency from being affected. Figure 2 illustrates multiple servers.

Cada um dos servidores pode ser construído e implantando individualmente. Fonte: .

Build-time integration

The build-time integration pattern is used when each micro frontend is delivered as a package to be included as a dependency in the container application configuration. This will produce a single JavaScript package for deployment, which brings benefits if the MFEs share the same dependencies. However, with this approach, for changes to a single micro frontend to be published,it is necessary for the container application to be rebuilt, thus requiring the reconstruction of the other MFEs that are making up the whole in asynchronized and coordinated way, a process also known as (lockstep) and subject to failures when launching the application.

The build-time integration approach is the least recommended. Although packaging is beneficial in some other contexts, in the context of MFEs it introduces coupling problems between different applications in the final deployment and launch process, impacting the autonomy of teams specializing in products.

Run-time integration via iframes

The run-time integration via iframes pattern, as well as the server-side template composition pattern, is not a new technique. The iframe (short for inline frame)is an old feature for Web pages,it was introduced in 1997 with HTML 4.01 by Microsoft's Internet Explorer browser through the element <iframe>. This feature allows you to embed an HTML document inside another HTML document. This option is the simplest approach to start dividing a monolith into small applications, but many people and teams that develop applications are not interestedin adopting it.

Considering the main characteristics of MFEs listed above, iframes are mostly suitable for implementing them, as long as care is taken in how to divide the application and structure the teams. By their nature, iframes make it easy to build a page from independent subpages. They also offer a good degree of isolation in terms of style and global variables that don't interfere with each other. However, this easy isolation tends to make them less flexible than other options. It can be difficult to build integrations between different MFEs, so with iframes, routing, history and deep-linking become more complicated. Additionally, iframes present some extra challenges to making a page fully mobile-friendly.

Run-time integration via JavaScript

The un-time integration via JavaScript pattern is used when each micro frontend is included in the container application page using a tag <script> and, after the page loads, exposes a global function as an entry point. The container application then determines which micro frontend should be mounted and calls the relevant function to tell the micro frontend when and where it should be displayed. Unlike the integration pattern at build time, it is possible to deploy each of the JavaScript files of each micro frontend independently. And, unlike standard iframes, you have complete flexibility to build integrations between MFEs in the desired way. For example, only downloading each JavaScript package as needed, or passing data in or out of applications when displaying a micro frontend. The flexibility of this approach, combined with the capacity for independent implementation, has led this pattern being adopted by teams more frequently than other patterns.

Run-time integration via Web Components

The run-time integration via Web Components pattern is a variation of the JavaScript integration approach. Web Components is a consolidated standard for creating custom components without using frontend frameworks [Taibi e Mezzalira 2022]. In this approach, each micro frontend defines and creates a custom HTML element for the container application to display, rather than defining a global function for the container to call. The end resultis quite similar to the standard via JavaScript, the main differenceis the team can combine with the Web Components standard when composing MFEs. Here the team must decide, according to preference and mastery of techniques, whether they prefer to use the Web Components specifications and use the resources that the browser offers, or define their own interface between the container application and the MFEs through the standard via JavaScript.

The five patterns described above were mapped by [Jackson 2019]. However, in 2020, a major event impacted the frontend development scene: the launch of a technology that also proposed a new standard for applications with Micro Frontend architecture. Zack Jackson and Tobias Koppers, creators of Webpack – a tool widely adopted by teams for the packaging process – announced the launch of the Module Federation pattern. In the software industry, “federated” means a collaborative yet decentralized and interoperable approach to building systems or applications.

Federação de Módulos

This pattern allows a JavaScript application to dynamically load the code of another smaller application. It is a mix of the best of build-time and run-time integration via JavaScript patterns, but with the tooling support of the Webpack module federation feature. Through this feature, it is possible to associate several separate applications that act as containers, with the possibility of exposing and consuming code from other applications (as illustrated in Figure 3), resulting in a unified application for the end user.

Padrão Federação de Módulos em alto nível. Fonte: .

Some general concepts form the module federation pattern. Separate applications can be distinguished into local modules and remote modules, as illustrated in Figure 4. Local modules are regular modules that are part of the same application and are built together. Remote modules are those that are not part of the application, therefore they are built and packaged in another process, but are loaded at run time from a remote container. A container is created through a container entry, which exposes asynchronous access to specific modules. Containers can be nested and also use modules from other containers. Circular dependencies between containers are also possible. Each application that has its own build process acts as a container and also consumes other builds as containers. This way, each build is able to access any other exposed module by loading it from its container.

Figure 4: Details in abstraction of the integration of module types of the Module Federation pattern. Source: Zack Jackson and Tobias Koppers 2020.

Shared modules are replaceable modules and are provided as replacements for nested containers. They usually point to the same module in each build, e.g. the same library.

Using the Webpack tool to implement the module federation architecture helps with delivering all the benefits of MFEs and solves some known issues, such as dependency redundancy, which is addressed with shared modules. At the same time, the tool creates technological dependence on it, forcing all teams to use Webpack for the build process of their applications [Webpack 2023], [Zack Jackson 2020], [Zack Jackson and Tobias Koppers 2020].

Bibliography

  1. [Rising 1998] Linda Rising. The Patterns Handbook: Techniques, Strategies, and Applications. SIGS Reference Library. SIGS, 1998.
  2. [Jackson 2019] Cam Jackson. Micro Frontends. https://martinfowler.com/articles/ micro-frontends.html. Acesso em: Dezembro 2023. 2019.
  3. [Taibi e Mezzalira 2022] Davide Taibi e Luca Mezzalira. Micro-frontends: principles, implementations, and pitfalls. SIGSOFT Softw. Eng. Notes 47.4 (set. de 2022), pp. 25-29.
  4. [Zack Jackson and Tobias Koppers 2020] Zack Jackson and Tobias Koppers. Module Federation in Webpack 5. https://github.com/sokra/slides/blob/master/content/ModuleFederationWebpack5.md. 2020.
  5. [Webpack 2023] Webpack. Module Federation. https://webpack.js.org/concepts/module-federation/. 2023.
  6. [Zack Jackson 2020] Zack Jackson. Webpack 5 Module Federation: A game-changer in JavaScript architecture. https://medium.com/swlh/webpack-5-module-federation- a-game-changer-to-javascript-architecture-bcdd30e02669. 2020.