Webpack 5 Module Federation: Sharing Code Between Independently Deployed Apps
Webpack 5 Module Federation lets separate builds share modules at runtime, but it couples availability and version contracts. Learn when it fits and how to verify it.
03 Oct 2025, 08:34 UTC

The problem and the takeaway
Teams often split a frontend into independently deployed applications: one team owns the checkout SPA, another owns the catalog SPA, and both need the same design-system components and the same copy of React. Copying the library into every build wastes bytes, and publishing a versioned package to a registry couples every consumer to a release cycle.
Takeaway: Webpack 5 Module Federation lets independently built applications expose and consume modules at runtime through a remote entry manifest. It is useful when independent deployment matters more than operational simplicity, because it introduces a runtime availability dependency and a version contract between builds.
Requirements
- Separate webpack builds that deploy independently.
- A shared set of modules that consumers import by path.
- A reachable HTTP origin for each remote's entry file.
- Agreement on shared dependency versions, typically semver-compatible.
Smallest suitable design
Start with one host application and one remote application. The remote builds an entry file, conventionally named remoteEntry.js, that re-exports selected modules. The host declares that URL in remotes and imports the module dynamically. Shared dependencies such as react are declared in shared so both builds use one copy when versions are compatible.
Terms used below:
- remote entry: a generated webpack manifest that maps exposed module names to chunk URLs.
- exposes: mapping from a public module path to a local source file.
- remotes: mapping from an alias to a remote entry URL.
- shared: dependencies that federation may load once and reuse across builds.
Configuration example
Run the build command in each application's project directory. No special operating-system permissions are required; the process only needs read access to source files and write access to dist/. Replace placeholders such as REMOTE_ORIGIN with your actual deployment URL.
Remote application
const { ModuleFederationPlugin } = require('webpack').container;
module.exports = {
name: 'remoteApp',
entry: './src/index.js',
output: {
publicPath: 'auto',
clean: true,
},
plugins: [
new ModuleFederationPlugin({
name: 'remoteApp',
filename: 'remoteEntry.js',
exposes: {
'./Button': './src/Button',
},
shared: ['react', 'react-dom'],
}),
],
};
Host application
const { ModuleFederationPlugin } = require('webpack').container;
module.exports = {
name: 'hostApp',
entry: './src/index.js',
output: {
publicPath: 'auto',
clean: true,
},
plugins: [
new ModuleFederationPlugin({
name: 'hostApp',
remotes: {
remoteApp: 'remoteApp@REMOTE_ORIGIN/remote/remoteEntry.js',
},
shared: ['react', 'react-dom'],
}),
],
};
Expected checks after building:
- The remote
dist/containsremoteEntry.js. - The host build emits chunks that reference the declared remote entry URL.
- In the browser network panel,
remoteEntry.jsloads from the declared origin before the exposed module is used. - With
sharedenabled, React appears once across federated chunks; without it, React may be duplicated in both builds.
Risks:
- An incorrect
publicPathproduces 404s when the browser requests remote chunks. - Cross-origin requests may be blocked by CORS if the remote origin does not allow the host origin.
- Remote code executes with the host page's origin, so a compromised remote build can access the same cookies and storage as the host application.
Trust and data boundaries
Treat a remote entry URL as executable code, not merely a data endpoint. The browser loads the remote manifest and any chunks it references inside the host page, so the remote build runs with the host application's origin privileges. Validate the remote origin, use HTTPS, and expose only modules that are safe for consumers. Webpack federation does not verify remote entry signatures by default.
Operational checks
- Build both apps and inspect
dist/forremoteEntry.jsand shared chunks. - Load the host in a browser, open the network panel, and confirm the remote entry script fetches from the declared origin.
- Build with and without
sharedand compare asset sizes to verify common libraries are not duplicated. - Stop the remote server and reload the host. The host should surface a graceful error rather than a silent blank crash, because dynamic imports of remote modules reject when the entry is unreachable.
Failure modes
| Failure | Symptom | Cause |
|---|---|---|
| Remote deployment down | Host build succeeds; runtime chunk load fails | Remote entry URL is unreachable at runtime |
| Exported shape changes | Both builds compile; consumer crashes at runtime | Remote changed export names or types without coordinating the host |
| Shared version mismatch | Duplicate library copies or hook errors | Semver-incompatible versions satisfy different singleton ranges |
| Sourcemaps across boundary | Harder to trace errors to remote source | Chunks originate from separate builds |
Conditions that would change the design
Reconsider federation if:
- Both applications are released by the same pipeline on the same schedule. A versioned shared package may be simpler.
- You need server-side rendering. Runtime remote entry loading complicates server rendering; verify framework support before adopting federation.
- You cannot tolerate any runtime fetch failure for core UI. A build-time dependency degrades more predictably.
Webpack 5 minor releases can change federation edge cases, and shared dependency resolution depends on semver compatibility. Pin the webpack minor version across federated builds and test upgrades in isolation.
Rollback
Removing ModuleFederationPlugin and replacing remote imports with direct package imports restores the previous build behavior. Because this is a configuration change, roll back by reverting the commit and redeploying; there is no database state to migrate.
Limitation and practical check
The only reliable way to confirm federation behavior is to build and load the application in a browser; static analysis cannot guarantee runtime chunk availability. Check the network panel after every remote deploy.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.