Optimize Runtime Size
The Module Federation runtime includes remote consumption, shared dependencies, and Manifest / Snapshot capabilities by default. This covers most use cases out of the box, but code for unused capabilities can still be included in the final output.
Use experiments.optimization to remove capabilities that a build will definitely not use and reduce its runtime size.
These options remove code at build time. They are not feature flags that can be re-enabled after the page starts. Calling an API whose capability was removed throws an error. Rebuild and redeploy after changing an option.
Decide what this build needs
Do not decide from the Host or Remote label alone. A Remote can consume other Remotes, while a Host can avoid shared dependencies entirely. Base the decision on what this build actually does.
disableRemote removes the ability of the current build to consume other Remotes. It does not remove the producer-side exposes or container.get generated by the bundler. A producer that only exposes modules and never consumes another Remote can still enable it.
When a build has no exposes, the Webpack and Rspack plugins also remove container entry initialization from the consumer's main.js automatically. No disableExpose option is needed. This does not change the producer's remoteEntry.js.
Configuration
Webpack and Rspack accept the same options in ModuleFederationPlugin:
For Webpack, change the import to @module-federation/enhanced/webpack.
This combination is suitable for a minimal producer that only exposes modules, does not consume other Remotes, does not use shared dependencies, and does not depend on Manifest / Snapshot data. Start from the defaults and enable only options that are safe for your build.
Configure a runtime-only project with environment variables
If your project bundles @module-federation/runtime or @module-federation/runtime-core directly without ModuleFederationPlugin, use environment variables and replace them with build-time booleans in your bundler configuration.
For example, a project that does not consume Remotes, use shared dependencies or Snapshot data, and has no exposes can build with:
Webpack must replace the values explicitly:
With Rspack, pass the same federationDefines object to rspack.DefinePlugin. With Vite, pass it to the top-level define option.
Leaving environment variables as runtime strings is not enough. The bundler must replace them with true or false at build time so the minifier can remove the corresponding code. All capabilities remain enabled when no value is provided, preserving existing behavior.
What each option removes
disableRemote
Removes remote registration, entry loading, preloading, exposed-module retrieval and execution. It also removes Snapshot handling used only for remote loading and the remote-loading function generated by Webpack.
Suitable for:
- producers that only expose modules and never consume another Remote;
- standalone builds without
remotesthat never register a Remote at runtime.
Do not use it for:
- Hosts with configured
remotes; - applications that call
loadRemote,registerRemotes, orpreloadRemote; - applications that rely on a Manifest to discover or load Remotes dynamically.
disableShared
Removes shared dependency registration, selection, and loading, together with Webpack shared consumption, shared initialization, initial shared installation, fallback handling, and the shared tree-shaking plugin. A minimal empty share scope remains so a remote entry that does not use shared dependencies can still initialize.
Use it only when the build has no shared configuration and never registers or loads a shared dependency through runtime APIs.
Keep this capability when React, Vue, a component library, or another dependency must be reused across applications, remain a singleton, or participate in version selection.
disableSnapshot
Removes Manifest / Snapshot and related preload capabilities. It can reduce the output further, but its impact is broader than the other options.
Enable it only when using plain JavaScript Remotes without type synchronization, hot updates, preloading, DevTools, dynamic discovery, or another Snapshot-dependent feature. See the Manifest / Snapshot guide for the complete impact.
Common combinations
Producer that only exposes modules
If it does not consume other Remotes, enable:
Enable disableShared or disableSnapshot as well only when the producer does not use those capabilities.
Host without shared dependencies
The Host still needs remote consumption, so disable only shared handling:
Lightweight Host using plain JavaScript Remotes
If it does not use shared dependencies or Manifest / Snapshot data:
Remote consumption must remain enabled.
Difference from externalRuntime
externalRuntime extracts runtime code from each remoteEntry.js so multiple builds can reuse one external runtime. It mainly reduces duplicate downloads. disableRemote, disableShared, and disableSnapshot remove capabilities that the build does not need.
You can combine both approaches: remove unused capabilities first, then use externalRuntime to reduce duplicated code across outputs. When using an external runtime, the page must provide a compatible runtime in advance. See experiments.externalRuntime for configuration details.
Verify that the optimization works
1. Establish a comparable baseline
Record the output size before optimization with the same build mode, minification settings, and dependency versions. Do not compare development output with production output.
2. Enable one option at a time
Build and record the size of remoteEntry.js or the file that actually contains the runtime. Confirm each reduction before combining options so it is easier to identify both the benefit and any lost behavior.
The repository test fixture produced the following results. All three builds target the web and disable Snapshot support to isolate the two options. These values illustrate the relative reduction; actual results vary by project and version.
When exposes is not configured, the reduction affects the consumer's main.js, not the producer's remoteEntry.js. The following builds use the same entry, dependencies, and production settings; only container entry initialization changes.
3. Test real application flows
At minimum, verify:
- initial page load and refresh;
- every remote module entry;
- dynamic registration and preload paths;
- shared dependency singleton and version behavior;
- development hot updates and type synchronization;
- DevTools, runtime plugins, and monitoring.
If an explicit disabled-capability error appears, the build still needs that capability. Restore the corresponding option to false and rebuild.