Solving Micro-Frontend Bloat with Webpack Module Federation
Learn how to eliminate duplicate dependencies in micro-frontends using Webpack Module Federation to share code at runtime without sacrificing independent deployment.
30 Nov 2025, 04:33 UTC

The Dependency Duplication Problem
When splitting a large application into micro-frontends, teams often face a frustrating trade-off: either create a monolithic shared library that requires every team to re-deploy whenever a single utility changes, or allow each team to manage their own dependencies, leading to the user downloading the same version of React or Lodash five different times.
The goal is to achieve independent deployment without sacrificing runtime efficiency. Webpack Module Federation (introduced in Webpack 5) solves this by allowing a build to consume code from another build at runtime, treating remote bundles as if they were local imports while intelligently deduplicating shared libraries.
How Module Federation Works
Unlike traditional NPM packages, which are bundled into the application at build time, Module Federation uses a runtime manifest. This manifest tells the browser where to find a remote container and which modules that container exposes.
The system relies on two primary concepts:
- Exposes: The remote application defines which components or functions are available for others to use.
- Remotes: The host application defines where to find these remote containers and gives them a local alias.
Crucially, the shared configuration allows both the host and remote to negotiate which version of a library to use. If both use React 18, Webpack will only download it once, regardless of which application loads first.
Practical Implementation: Exposing and Consuming
To implement this, you must use the ModuleFederationPlugin in your webpack.config.js. Assume we have two projects: a Utility App (Remote) and a Main App (Host).
1. The Remote Configuration (Utility App)
Run this configuration in the project providing the shared code. You must define a unique name for the container.
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
module.exports = {
plugins: [
new ModuleFederationPlugin({
name: "util_app",
filename: "remoteEntry.js",
exposes: {
"./MathUtils": "./src/utils/math.js",
},
shared: { react: { singleton: true }, "react-dom": { singleton: true } },
}),
],
};
2. The Host Configuration (Main App)
Run this in the project that will consume the utility. The remotes key maps the remote's name to its deployed URL.
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
module.exports = {
plugins: [
new ModuleFederationPlugin({
name: "main_app",
remotes: {
util_app: "util_app@http://localhost:3001/remoteEntry.js",
},
shared: { react: { singleton: true }, "react-dom": { singleton: true } },
}),
],
};
3. Consuming the Remote Module
In your application code, use a dynamic import to load the remote module. This ensures the application doesn't crash if the remote is momentarily unavailable during the initial page load.
import React, { Suspense } from 'react';
// The syntax is: [remoteName]/[exposedModule]
const RemoteMath = React.lazy(() => import("util_app/MathUtils"));
function App() {
return (
<Suspense fallback="Loading...">
<RemoteMath />
</Suspense>
);
}
Verification and Diagnostics
To verify the implementation, start both servers using webpack serve and open the Host application. Perform the following checks:
- Network Tab: Look for
remoteEntry.js. It should be fetched once. Check that shared libraries (like React) are not downloaded multiple times across different chunks. - Console: Ensure no "version mismatch" warnings appear. If they do, check that your
sharedconfig usessingleton: truefor libraries that maintain a global state.
Trade-offs and Runtime Risks
Module Federation is powerful, but it shifts complexity from build-time to runtime. This introduces specific risks:
- Availability: If the remote server hosting
remoteEntry.jsgoes down, the host application may fail to render the remote component. Always wrap remote imports in a React Error Boundary or a similar fallback mechanism. - Version Drift: While
singleton: trueprevents duplicate loads, it can cause runtime crashes if the remote requires a version of a library that is incompatible with the host's version. - Security: You are executing code from a remote URL. Ensure your remote containers are served over HTTPS and that you have strict CORS (Cross-Origin Resource Sharing) policies in place to prevent unauthorized domains from consuming your modules.
Closing Action
If you are managing a project with more than three independent teams contributing to a single UI, stop relying on shared NPM packages for internal components. Migrate your shared utilities to a Module Federation remote to decouple your deployment cycles while keeping your bundle sizes lean.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.