Step-by-Step Webpack 5 Container Configuration #
Enterprise frontend teams frequently encounter critical runtime failures when isolating UI components into distributed containers. This guide delivers a precise workflow to eliminate eager consumption errors, resolve singleton mismatches, and establish stable remote entry points. By following this structured approach, architects can safely decouple legacy builds without breaking cross-application state management.
Key Implementation Objectives:
- Identify exact
ModuleFederationPluginmisconfigurations causingShared module is not available for eager consumption - Implement strict singleton version pinning for React and state management libraries
- Validate remote entry generation and network payload delivery across staging environments
- Establish CI/CD guardrails to prevent dependency drift in distributed container deployments
Problem Context #
Container initialization in enterprise environments typically fails due to divergent build artifacts and runtime environment constraints. Common failure patterns include console errors indicating missing remote entries, duplicate framework instances, or chunk resolution timeouts. The divergence between local development servers (HMR-enabled, direct file serving) and production CDN delivery (immutable hashing, edge caching) often masks configuration drift until deployment.
Understanding the foundational architecture outlined in Webpack & Vite Module Federation Implementation is critical for isolating these environment-specific failures. Teams must account for strict corporate constraints, including Node.js 18+, Webpack 5.88+, and reverse proxy routing that strips or alters Origin headers during cross-origin requests.
Root Cause Analysis #
Container failures at runtime stem from four primary misconfigurations:
- Eager Consumption: Shared dependencies (e.g., React, Redux) are imported synchronously in the entry point before the Module Federation runtime initializes. This triggers
Shared module is not available for eager consumptionbecause the host cannot inject the shared scope in time. - Remote URL Resolution: Hardcoded
localhostURLs in theremotesconfiguration fail in staging/production due to missing CORS headers, incorrect proxy mappings, or missing trailing slashes. - Version Mismatch in Shared Scope: The
sharedarray lacks strict version constraints. Webpack rejects singleton loading when minor/patch versions diverge across host and remote builds. - Broken Chunk Resolution: Missing or misconfigured
publicPathcauses the browser to request chunks from incorrect relative paths, especially in containerized deployments behind reverse proxies.
Referencing Configuring Webpack Module Federation principles clarifies how Webpack’s dependency graph resolves these boundaries at compile time versus runtime.
Step-by-Step Fix #
Apply the following configuration patches to resolve initialization and dependency sharing failures:
- Defer Entry Execution: Replace synchronous imports in
src/index.jswith an async bootstrap pattern. This guarantees the federation runtime initializes before shared modules are requested. - Enforce Strict Shared Dependencies: Configure the
sharedproperty withsingleton: true,eager: false, and explicitrequiredVersionranges. This prevents duplicate React trees and hooks violations. - Stabilize Remote Entry & Public Path: Explicitly set
filename: 'remoteEntry.js'and usepublicPath: 'auto'to dynamically resolve chunk URLs across different deployment paths. - Implement Fallback Boundaries: Wrap remote component consumption in React Error Boundaries to gracefully handle network timeouts or remote build failures.
// webpack.config.js
const { ModuleFederationPlugin } = require('webpack').container;
module.exports = {
entry: './src/index.js',
output: {
publicPath: 'auto',
clean: true
},
plugins: [
new ModuleFederationPlugin({
name: 'containerApp',
filename: 'remoteEntry.js',
exposes: {
'./Dashboard': './src/components/Dashboard',
'./UserProfile': './src/components/UserProfile'
},
shared: {
react: { singleton: true, requiredVersion: '^18.2.0', eager: false },
'react-dom': { singleton: true, requiredVersion: '^18.2.0', eager: false },
'@tanstack/react-query': { singleton: true, requiredVersion: '^4.0.0', eager: false }
}
})
]
};
Validation #
Verify successful container build, runtime module resolution, and cross-application communication using these deterministic checks:
- Network Inspection: Open browser DevTools → Network tab. Confirm
remoteEntry.jsand all shared chunks return200 OKwith correctContent-Type: application/javascript. - Dependency Tree Analysis: Run
webpack --analyzeorwebpack-bundle-analyzer. Verify isolated dependency trees and confirm shared modules are not duplicated in the host or remote bundles. - Runtime Console Check: Execute
window.__webpack_init_sharing__('default')in the console. It must returnundefined(indicating successful initialization) rather than throwing a scope collision error. - CORS & Preflight Validation: Inspect XHR/Fetch requests to remote endpoints. Ensure
Access-Control-Allow-Originmatches the host domain and preflightOPTIONSrequests succeed.
Prevention #
Establish architectural guardrails to prevent regression during iterative container deployments:
- CI/CD Dependency Audits: Integrate
npm auditand custom scripts into pipelines to flag singleton version drift before merge. Fail builds ifpackage.jsonmajor versions diverge across micro-frontends. - Standardized Configuration Templates: Distribute a shared Webpack config package or monorepo template to enforce consistent
ModuleFederationPluginsettings across all repositories. - Runtime Health Checks: Implement lightweight endpoint monitoring that polls
remoteEntry.jsavailability and validates shared dependency integrity during deployment canary phases. - Fallback Routing Documentation: Define and document degraded state routing (e.g., static placeholders or host-native fallbacks) to maintain UX when remote containers are temporarily unavailable.
Code Examples #
Dynamic Remote Import with Runtime Initialization
// src/bootstrap.js
import('./App').catch(err => {
console.error('Container bootstrap failed:', err);
// Render fallback UI
});
// src/index.js
import('./bootstrap');
// Host consumption pattern
const RemoteDashboard = React.lazy(() => import('containerApp/Dashboard'));
Implementation Note: Implements lazy initialization to defer module loading until after the federation runtime is fully initialized, resolving eager consumption errors.
Expected Runtime Log Output
[webpack-dev-server] Project is running at: http://localhost:3001/
[webpack-dev-server] Content not from webpack is served from '/public' directory
[ModuleFederation] Loading remote entry: http://localhost:3001/remoteEntry.js
[ModuleFederation] Shared module 'react' resolved as singleton v18.2.0
[ModuleFederation] Container initialized successfully. No eager consumption detected.
Implementation Note: Confirms successful remote entry resolution, singleton sharing, and absence of eager consumption warnings.
Common Pitfalls #
| Issue | Root Cause & Resolution |
|---|---|
| Eager Consumption of Shared Dependencies | Synchronous imports in index.js execute before the federation runtime initializes. Fix: Defer all imports using dynamic import() or an async bootstrap pattern. |
| Incorrect Remote URL Resolution in Development | Hardcoded localhost URLs in remotes ignore dev server port mapping or proxy rules. Fix: Use environment variables or devServer.proxy to dynamically resolve endpoints. |
| Duplicate Framework Instances at Runtime | Missing singleton: true and eager: false in shared config spawns multiple React instances. Fix: Enforce strict version pinning and singleton configuration across all containers. |
Frequently Asked Questions #
Why does Webpack throw ‘Shared module is not available for eager consumption’?
This occurs when a shared dependency (like React) is imported synchronously in the entry file before the Module Federation runtime initializes. Resolve it by deferring imports via dynamic import() or an async bootstrap file.
How do I prevent duplicate React instances across micro-frontend containers?
Configure the shared object in ModuleFederationPlugin with singleton: true and specify a strict requiredVersion. Ensure all containers and hosts use identical major versions of the framework.
What is the correct way to expose components from a Webpack 5 container?
Use the exposes property in the plugin configuration with relative paths from the container’s root. Map them to internal component files, then consume them in the host via React.lazy(() => import('containerName/Component')).
How can I validate that my remoteEntry.js is loading correctly?
Check the Network tab for a 200 OK status on remoteEntry.js, verify CORS headers are present, and confirm that window.__webpack_init_sharing__('default') executes without errors in the browser console.