Runtime Hooks

beforeInit

SyncWaterfallHook

Updates the corresponding init configuration before the MF instance is initialized.

  • type
function beforeInit(args: BeforeInitOptions): BeforeInitOptions

type BeforeInitOptions ={
    userOptions: UserOptions;
    options: ModuleFederationRuntimeOptions;
    origin: ModuleFederation;
    shareInfo: ShareInfos;
}

interface ModuleFederationRuntimeOptions {
  id?: string;
  name: string;
  version?: string;
  remotes: Array<Remote>;
  shared: ShareInfos;
  plugins: Array<ModuleFederationRuntimePlugin>;
  inBrowser: boolean;
}

init

SyncHook

Called after the MF instance is initialized.

  • type
function init(args: InitOptions): void

type InitOptions ={
  options: ModuleFederationRuntimeOptions;
  origin: ModuleFederation;
}

beforeRequest

AsyncWaterfallHook

Called before resolving the remote path, useful for updating something before lookup.

  • type
async function beforeRequest(args: BeforeRequestOptions): Promise<BeforeRequestOptions>

type BeforeRequestOptions ={
  id: string;
  options: ModuleFederationRuntimeOptions;
  origin: ModuleFederation;
}

afterResolve

AsyncWaterfallHook

Called after resolving the remote path, allowing modification of the resolved content.

  • type
async function afterResolve(args: AfterResolveOptions): Promise<AfterResolveOptions>

type AfterResolveOptions ={
  id: string;
  pkgNameOrAlias: string;
  expose: string;
  remote: Remote;
  options: ModuleFederationRuntimeOptions;
  origin: ModuleFederation;
  remoteInfo: RemoteInfo;
  remoteSnapshot?: ModuleInfo;
}

onLoad

AsyncHook

Triggered once a federated module is loaded, allowing access and modification to the exports of the loaded file.

  • type
async function onLoad(args: OnLoadOptions): Promise<void>

type OnLoadOptions ={
  id: string;
  expose: string;
  pkgNameOrAlias: string;
  remote: Remote;
  options: ModuleOptions;
  origin: ModuleFederation;
  exposeModule: any;
  exposeModuleFactory: any;
  moduleInstance: Module;
}

type ModuleOptions = {
    remoteInfo: RemoteInfo;
    host: ModuleFederation;
}

interface RemoteInfo {
  name: string;
  version?: string;
  buildVersion?: string;
  entry: string;
  type: RemoteEntryType;
  entryGlobalName: string;
  shareScope: string;
}

handlePreloadModule

SyncHook

Handles the preloading logic for remotes.

  • type
function handlePreloadModule(args: HandlePreloadModuleOptions): void

type HandlePreloadModuleOptions ={
  id: string;
  name: string;
  remoteSnapshot: ModuleInfo;
  preloadConfig: PreloadRemoteArgs;
}

errorLoadRemote

AsyncHook

Called if loading remotes fails, enabling custom error handling. Can return a custom fallback logic.

  • type
async function errorLoadRemote(args: ErrorLoadRemoteOptions): Promise<void | unknown>

type ErrorLoadRemoteOptions ={
  id: string;
  error: unknown;
  options?: any;
  from: 'build' | 'runtime';
  lifecycle: 'beforeRequest' | 'beforeLoadShare' | 'afterResolve' | 'onLoad';
  origin: ModuleFederation;
}

The lifecycle parameter indicates the stage where the error occurred:

  • beforeRequest: Error during initial request processing
  • afterResolve: Error during manifest loading (most common for network failures)
  • onLoad: Error during module loading and execution
  • beforeLoadShare: Error during shared dependency loading
  • example
import { createInstance, loadRemote } from '@module-federation/enhanced/runtime'
import type { ModuleFederationRuntimePlugin } from '@module-federation/enhanced/runtime';

const fallbackPlugin: () => ModuleFederationRuntimePlugin =
  function () {
    return {
      name: 'fallback-plugin',
      errorLoadRemote(args) {
        const { lifecycle, id, error } = args;
        
        // Log error details safely
        if (error) {
          console.warn(`Failed to load remote ${id} at ${lifecycle}:`, error?.message || error);
        }
        
        // Handle different error types based on lifecycle
        switch (lifecycle) {
          case 'afterResolve':
            // Manifest loading failed - provide fallback manifest or alternative URL
            return {
              id: id || 'fallback',
              name: id || 'fallback',
              metaData: { /* fallback manifest */ },
              shared: [],
              remotes: [],
              exposes: []
            };
          
          case 'beforeRequest':
            // Request processing failed - can return modified args or void
            console.warn(`Request processing failed for ${id}`);
            return void 0;
          
          case 'onLoad':
            // Module loading failed - provide fallback component
            return () => ({
              __esModule: true,
              default: () => 'Fallback Component'
            });
          
          case 'beforeLoadShare':
            // Shared dependency loading failed - return fallback shared module
            console.warn(`Shared dependency loading failed for ${id}`);
            return () => ({
              __esModule: true,
              default: {}
            });
          
          default:
            // Unknown lifecycle - log and return void
            console.warn(`Unknown lifecycle ${lifecycle} for ${id}`);
            return void 0;
        }
      },
    };
  };

const mf = createInstance({
    name: 'mf_host',
    remotes: [
        {
            name: "remote",
            alias: "app1",
            entry: "http://localhost:2001/mf-manifest.json"
        }
    ],
    plugins: [fallbackPlugin()]
});

mf.loadRemote('app1/un-existed-module').then(mod=>{
  expect(mod).toEqual('fallback');
});

beforeLoadShare

AsyncWaterfallHook

Called before loading shared, can be used to modify the corresponding shared configuration.

  • type
async function beforeLoadShare(args: BeforeLoadShareOptions): Promise<BeforeLoadShareOptions>

type BeforeLoadShareOptions ={
  pkgName: string;
  shareInfo?: Shared;
  shared: Options['shared'];
  origin: ModuleFederation;
}

resolveShare

SyncWaterfallHook

Allows manual setting of the actual shared module to be used.

  • type
function resolveShare(args: ResolveShareOptions): ResolveShareOptions

type ResolveShareOptions ={
  shareScopeMap: ShareScopeMap;
  scope: string;
  pkgName: string;
  version: string;
  GlobalFederation: Federation;
  resolver: () => Shared | undefined;
}
  • example
import { createInstance, loadRemote } from '@module-federation/enhanced/runtime'

import type { ModuleFederationRuntimePlugin } from '@module-federation/enhanced/runtime';

const customSharedPlugin: () => ModuleFederationRuntimePlugin =
  function () {
    return {
      name: 'custom-shared-plugin',
      resolveShare(args) {
        const { shareScopeMap, scope, pkgName, version, GlobalFederation } = args;

        if (
          pkgName !== 'react'
        ) {
          return args;
        }

        args.resolver = function () {
          shareScopeMap[scope][pkgName][version] = window.React; // replace local share scope manually with desired module
          return shareScopeMap[scope][pkgName][version];
        };
        return args;
      },
    };
  };


const mf = createInstance({
    name: 'mf_host',
    shared: {
      react: {
        version: '17.0.0',
        scope: 'default',
        lib: () => React,
        shareConfig: {
          singleton: true,
          requiredVersion: '^17.0.0',
        },
      },
    },
    plugins: [customSharedPlugin()]
});

window.React = ()=> 'Desired Shared';

mf.loadShare("react").then((reactFactory)=>{
  expect(reactFactory()).toEqual(window.React());
});

beforePreloadRemote

AsyncHook

Called before the preload handler executes any preload logic.

  • type
async function beforePreloadRemote(args: BeforePreloadRemoteOptions): BeforePreloadRemoteOptions

type BeforePreloadRemoteOptions ={
  preloadOps: Array<PreloadRemoteArgs>;
  options: Options;
  origin: ModuleFederation;
}

generatePreloadAssets

AsyncHook

Used to control the generation of resources that need to be preloaded.

  • type
async function generatePreloadAssets(args: GeneratePreloadAssetsOptions): Promise<PreloadAssets>

type GeneratePreloadAssetsOptions ={
  origin: ModuleFederation;
  preloadOptions: PreloadOptions[number];
  remote: Remote;
  remoteInfo: RemoteInfo;
  remoteSnapshot: ModuleInfo;
  globalSnapshot: GlobalModuleInfo;
}

interface PreloadAssets {
  cssAssets: Array<string>;
  jsAssetsWithoutEntry: Array<string>;
  entryAssets: Array<EntryAssets>;
}

createScript

SyncHook

Used to modify the script when loading resources.

  • type
function createScript(args: CreateScriptOptions): HTMLScriptElement | void

type CreateScriptOptions ={
  url: string;
}
  • example
import type { ModuleFederationRuntimePlugin } from '@module-federation/enhanced/runtime';

const changeScriptAttributePlugin: () => ModuleFederationRuntimePlugin =
  function () {
    return {
      name: 'change-script-attribute',
      createScript({ url }) {
        if (url === 'http://localhost:3001/remoteEntry.js') {
          let script = document.createElement('script');
          script.src = url;
          script.setAttribute('loader-hooks', 'isTrue');
          script.setAttribute('crossorigin', 'anonymous');
          return script;
        }
      }
    };
  };