How Module Federation Shares JavaScript Code at Runtime

Module Federation is an architectural pattern and build-tool mechanism that enables multiple independently deployed JavaScript applications to dynamically share code and dependencies at runtime. By decoupling module distribution from build-time bundling, it allows applications to act as micro-frontends or distributed systems that load shared libraries, components, and logic on demand without requiring a unified build pipeline or monolithic deployment.

Core Concepts of Module Federation

Module Federation relies on a decentralized architecture where applications define their sharing boundaries through configuration:

The remoteEntry.js Manifest

The foundation of runtime sharing is the remoteEntry.js file generated by the remote application during build time. This lightweight manifest acts as an entry point and interface contract for the host application:

  1. Exposed Module Mapping: It contains a lookup table of all modules the remote makes available.
  2. Shared Dependency Requirements: It declares the versions of shared libraries the remote requires, along with versioning rules (such as semantic version ranges and singleton requirements).
  3. Module Getters: It provides asynchronous factory functions to fetch and execute the remote code chunks on demand.

When the host application needs a remote module, it fetches this manifest at runtime, which tells the host exactly how and where to load the required assets.

The Shared Scope and Dependency Negotiation

To prevent redundant downloads of common dependencies (such as React, Vue, or utility libraries), Module Federation establishes a global runtime object called the Shared Scope.

When host and remote applications initialize in the browser:

  1. Registration: Both the host and remote register their available versions of shared dependencies in the shared scope.
  2. Version Resolution: The Module Federation runtime analyzes the semantic versioning (semver) requirements specified by both builds.
  3. Deduplication: If the versions are compatible, the runtime selects the highest compatible version, downloads it once, and provides it to both applications.
  4. Fallback & Fall-through: If a remote requires a version incompatible with the host’s version, and the dependency is not marked as a strict singleton, the runtime falls back to downloading the remote’s specific version independently.

Step-by-Step Runtime Execution Flow

  1. Host Initialization: The host application loads and initializes the global shared scope.
  2. Manifest Retrieval: The host requests the remoteEntry.js file from the remote’s server.
  3. Scope Initialization: The remote entry initializes itself using the host’s shared scope, merging its own dependency metadata.
  4. Asynchronous Import: When code calls import('remoteApp/Component'), the host queries the remote container.
  5. Chunk Fetching: The remote container dynamically downloads the specific JavaScript chunk containing the requested component.
  6. Execution: The fetched code executes within the context of the host application, utilizing the negotiated dependencies from the shared scope.

Through this process, Module Federation provides the operational independence of microservices with the performance and user experience of a unified single-page application.