Webpack Module Federation
Webpack Module Federation and the problem it tries to solve
I mentioned before how static code analysis, that is required to optimize code, can only be executed at buildtime. But what if we wanted to analyze our dependency graph to share dependencies of a horizontal composition, built and deployed independently, at runtime? That is not typically possible for most bundlers.
To mitigate this problem, Webpack introduced the concept of module federation enabled by a specific dedicated plugin that allows the system to perform static analysis of dependencies at runtime, and then share dependencies between scopes.
This approach makes it possible for each module to either provide or consume dependencies from the shareScope, as per additional configuration passed via the plugin configuration object.
Each module configured will be loaded as either host or remote, roles that are interchangeable.
Webpack Module Federation: Host module
A module that is loaded first will become the host, and will be responsible for loading the remote modules and providing the shared dependencies to the other modules via a global shareScope. There is only one host at a time.
Webpack Module Federation: Remote module(s)
Remotes are loaded immediately after the host and can both consume and provide dependencies from the shareScope. If a dependency required -or the defined version- is not available in the shareScope, they will load their own.
Challenges of Module Federation
Although Module Federation concepts are very interesting, teams will need to be equipped to solve some important challenges that need to be addressed:
- Version skew, typically when versions required by different modules are incompatible
- Fate sharing, typically when a bug in one of the modules leads to app malfunction, impacting other modules
- Additional efforts to accomplish UI cohesion and consistency
- Complexity to manage state and potential state duplication
- With independent teams potentially loading any technology to an horizontal split, the requirement for extended technical definitions becomes imperative
- Increased complexity to design the infrastructure mechanisms to support deployment
We may understand that the optimal usage is for a design that loads modules that are part of a same application framework, and that the choice of framework version -impacting dependencies compatibility-, state management, etc, is therefore implicit.