Micro Frontends with Module Federation in Webpack 5 Applications
Scale development and increase operational efficiency by breaking up Webpack 5 applications using micro frontends with Module Federation.
Imagine you are a Senior Enterprise Architect responsible for twelve separate business-critical applications. Each application serves a unique purpose, but they also share some common features. For example, all of the sites feature a search bar that allows users to search for specific content on the site.
Rather than having each app development team build and maintain their own search bar, wouldn’t it be great to build the search bar once and distribute it to every application inside your business?
Enter Module Federation.
- A collection of independent remote software modules
- Each module is autonomous and fully self contained
- Multiple modules are dynamically loaded at runtime to form a single page application, often referred to as the shell or host application
Going back to our example: using Module Federation, the search bar can be built by a single team and published as a remote module, then dynamically loaded at runtime by any application that wants to use that feature. The teams in charge of these applications don’t have to worry about creating or maintaining their own search experience. Instead, they can simply pull in the search bar using Module Federation, which handles all the complexities of loading and configuring the remote modules. On the user’s end, they experience it all as one single, fully integrated application.
How Module Federation works
However, to understand Module Federation, it’s important to distinguish between local and remote modules. Local modules are installed locally and packaged up in the application’s build process. Remote modules are not part of the application build and are instead loaded from a “container” at runtime.
Module Federation orchestrates the process of loading and dynamically configuring these remote modules, including dependency management. If a dependency is missing, the dependency will be automatically downloaded by the host application.
By dynamically loading and handling dependencies for remote modules at runtime, we avoid many common challenges with integrating local modules as part of the build process.
For example, when an update is published to a local module, we need to download the update and rebuild our app in order to take advantage of any updates, bug fixes, or new features. Similarly, the team that owns that module has to publish updates and make sure anyone using it has upgraded to the latest version. This is especially important for critical security updates. In practice, this means you likely have various versions of a module running around.
Incorporating local modules and troubleshooting module dependencies at build time also leads to “dependency hell,” where we can’t build our application without resolving a bunch of issues related to module dependencies.
In contrast, Module Federation allows us to focus on the core features of our app, while effectively outsourcing the management of certain features or experiences to the teams managing those remote modules.
How Module Federation solves problems of building apps at scale
Build and ship in parallel
Micro frontends with module federation give each development team greater autonomy over how their portion of the app should be built. It also allows multiple teams to work in parallel, without interfering with each other’s code. For large enterprises with complex applications and hundreds of developers contributing to the same project, Module Federation is essential.
Enforce brand and UX guidelines
By building an experience once and reusing it across multiple applications, brand and user experience (UX) teams can better enforce consistent design standards across all digital touch points. Managing a single module that can be repurposed, rather than consistently creating something new, leaves less room for human error. Standardizing on a single experience that runs everywhere will ensure that you’re giving users a consistent experience every time they interact with your brand.
Reuse code across applications
Module Federation improves operational efficiency by reusing the same code across multiple applications. Rather than having various development teams build the same experiences over and over again, Module Federation enables a single team to build an experience once and then safely distribute that experience to every other team inside the business. This saves time and avoids duplication of effort.
Tradeoffs of federated modules
One downside of Module Federation is that Webpack does not support “tree shaking” for shared dependencies across federated modules. Tree shaking is a method of stripping out unused code during the build process to reduce bundle sizes and improve application performance. Since tree shaking isn’t available with Module Federation, even if you only need a portion of the code in a remote module, you will still need to download the entire module. You may be able to get around this by manually configuring the host application, though it is not supported by the compiler.
Second, while Module Federation prevents many common build time issues, it introduces risk during run time, where encountering issues may be more problematic and could negatively impact the user experience. Dynamic loading of remote modules at run time may make it more challenging to conduct end-to-end QA testing, since part of the app’s functionality may not be available for testing at the time of development.
Finally, Module Federation is a feature of Webpack 5, so any applications that wish to take advantage of this feature must be using Webpack and be on the correct version.
How to use Module Federation in a mobile app
Once Capacitor apps are built and updated, Portals for Capacitor enables multiple apps to be published through Appflow to a single Capacitor mobile app. Module Federation creates the dependencies between them.
With Portals for Capacitor, all files live on-device so there is no network latency for runtime dependencies. This enables teams to work autonomously and push live updates independently within the same Capacitor App.
For those not using Capacitor, fear not - Portals can work with React Native, Swift, and Kotlin too.
How to get started with Application Module Federation
Given the size of the Webpack community, you’ll find a rich library of how-to videos, code samples, talks and presentations, and other resources to help you implement and optimize your use of Module Federation.