Mastering Module Federation: From NPM Sharing to Advanced Remote Loading

This article explains how to share UI modules via NPM packages and Module Federation, compares traditional iframe approaches, dives into low‑level and high‑level concepts, demonstrates practical webpack configurations, version‑selection strategies, and runtime loading mechanisms with detailed code examples.

WeDoctor Frontend Technology
WeDoctor Frontend Technology
WeDoctor Frontend Technology
Mastering Module Federation: From NPM Sharing to Advanced Remote Loading

Introduction

In real projects we often need to share UI components across multiple applications. The most common practice is to publish the component as an NPM package and import it via package.json. However, when many projects depend on the same component, manual updates become painful.

NPM‑based Sharing

We can package a carousel component as an NPM module, add it to dependencies, and let each host project compile it. This works for simple cases but fails when a shared module must be updated simultaneously across all consumers.

Module Federation – Share Sub‑App

Traditional micro‑frontend solutions use iframe which brings communication, SEO, caching, and performance issues. Module Federation allows independent builds to expose and consume modules at runtime without hard dependencies.

Let’s explore the design through configuration examples.

Low‑level Concepts – Local and Remote Modules

The diagram likens a host’s local module to a molecule (container) and a remote module to an atom (shared piece). Each host treats its own code as a molecule, while the remote code is an atom that can be loaded asynchronously.

Each Host sees its own code as a local module (molecule).

Each Remote is a remote module (atom) loaded at runtime.

A container is created through a container entry, exposing asynchronous access to specific modules. The access is split into two steps: Loading the module (asynchronous) Evaluating the module (synchronous)

High‑level Concepts – Bidirectional Sharing and Inference

When two projects need to share functionality, copying code leads to duplicated updates. Module Federation solves this by allowing both sides to expose and consume each other’s modules.

Example: Regular MF Usage

new ModuleFederationPlugin({
  name: "app1",
  remotes: { app2: `app2@${getRemoteEntryUrl(3002)}` },
});

new ModuleFederationPlugin({
  name: "app2",
  filename: "remoteEntry.js",
  exposes: { "./ButtonContainer": "./src/ButtonContainer" },
  remotes: { app3: `app3@${getRemoteEntryUrl(3003)}` },
});

new ModuleFederationPlugin({
  name: "app3",
  filename: "remoteEntry.js",
  exposes: { "./Button": "./src/Button" },
});

Loading Module Code

// Simplified excerpt of the runtime loader
var moduleMap = { "./Button": () => Promise.all([__webpack_require__.e("webpack_sharing_consume_default_react_react-_0085"), __webpack_require__.e("src_Button_js")]).then(() => __webpack_require__("./src/Button.js")) };
function get(module, getScope) { /* … */ }
function init(shareScope, initScope) { /* … */ }
__webpack_require__.d(exports, { get: () => get, init: () => init });

Version Selection

Using singleton: true shares a single instance of a package. When hosts require different versions, Module Federation picks the highest compatible version unless requiredVersion is set to false to disable inference.

// Host package.json
"dependencies": { "mf-test-ssy": "^1.0.0" }
// Remote package.json
"dependencies": { "mf-test-ssy": "^2.0.0" }

new ModuleFederationPlugin({
  shared: {
    react: { singleton: true },
    "react-dom": { singleton: true },
    "mf-test-ssy": { singleton: true },
  },
});

Experiments show that the remote with the higher version is used when the host’s version is lower, while the opposite direction keeps the host’s version.

Automatic Inference Settings

The packageName option lets you specify which package to look up. By default Module Federation infers the request; setting requiredVersion: false disables this behavior.

Scope and Runtime Sharing

The runtime creates a shared scope object ( __webpack_require__.S) and registers each shared module with its version, eager flag, and source. The SharePlugin generates ConsumeSharedPlugin and ProvideSharedPlugin configurations that handle the actual loading and initialization.

class SharePlugin {
  constructor(options) {
    const sharedOptions = parseOptions(...);
    this._shareScope = options.shareScope;
    this._consumes = /* … */;
    this._provides = /* … */;
  }
  apply(compiler) {
    new ConsumeSharedPlugin({ shareScope: this._shareScope, consumes: this._consumes }).apply(compiler);
    new ProvideSharedPlugin({ shareScope: this._shareScope, provides: this._provides }).apply(compiler);
  }
}
module.exports = SharePlugin;

Conclusion

Module Federation treats shared modules as atoms that can be loaded on demand, while local modules act as molecules that compose the application. Using shared scopes, version inference, and singleton settings, developers can avoid duplicated updates and achieve efficient, runtime‑driven code sharing across micro‑frontends.

Other MF Ecosystem

ExternalTemplateRemotesPlugin

For dynamic remote URLs and cache invalidation, the plugin allows runtime URL substitution.

new ModuleFederationPlugin({
  remotes: { 'my-remote-1': 'my-remote-1@[window.remote-1-domain]/remoteEntry.js?[getRandomString()]' }
}),
new ExternalTemplateRemotesPlugin();

References

https://webpack.js.org/concepts/module-federation/#building-blocks

https://github.com/sokra/slides/blob/master/content/ModuleFederationWebpack5.md

https://www.youtube.com/watch?v=x22F4hSdZJM

https://github.com/module-federation/module-federation-examples

https://segmentfault.com/a/1190000039031505

http://img.iamparadox.club/img/mf2.jpg

https://developer.aliyun.com/article/755252

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaScriptModule FederationWebpackFrontend ArchitecturenpmMicro Frontendsshared modules
WeDoctor Frontend Technology
Written by

WeDoctor Frontend Technology

Official WeDoctor Group frontend public account, sharing original tech articles, events, job postings, and occasional daily updates from our tech team.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.