Runtime Hooks

beforeInit

SyncWaterfallHook

在 MF 实例初始化之前更新对应 init 配置

  • 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

在 MF 实例初始化后调用

  • type
function init(args: InitOptions): void  type InitOptions ={  options: ModuleFederationRuntimeOptions;  origin: ModuleFederation; }

beforeRequest

AsyncWaterfallHook

在解析 remote 路径前调用,对于在查找之前更新某些内容很有用。

  • type
async function beforeRequest(args: BeforeRequestOptions): Promise<BeforeRequestOptions>  type BeforeRequestOptions ={  id: string;  options: ModuleFederationRuntimeOptions;  origin: ModuleFederation; }

afterResolve

AsyncWaterfallHook

在解析 remote 路径后调用,允许修改解析后的内容。

  • 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.

加载 remote 后触发,允许访问和修改已加载文件的导出(exposes)。

  • 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

处理 remotes 的预加载逻辑。

  • type
function handlePreloadModule(args: HandlePreloadModuleOptions): void  type HandlePreloadModuleOptions ={  id: string;  name: string;  remoteSnapshot: ModuleInfo;  preloadConfig: PreloadRemoteArgs; }

errorLoadRemote

AsyncHook

如果加载 remotes 失败,则调用,从而启用自定义错误处理。可返回自定义的兜底逻辑。

  • type
async function errorLoadRemote(args: ErrorLoadRemoteOptions): Promise<void | unknown>  type ErrorLoadRemoteOptions ={  id: string;  error: unknown;  from: 'build' | 'runtime';  origin: ModuleFederation; }
  • example
import { createInstance } from '@module-federation/enhanced/runtime'  import type { ModuleFederationRuntimePlugin } from '@module-federation/enhanced/runtime';  const fallbackPlugin: () => ModuleFederationRuntimePlugin =  function () {  return {  name: 'fallback-plugin',  errorLoadRemote(args) {  const fallback = 'fallback'  return fallback;  },  };  };   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

在加载 shared 之前调用,可用于修改对应的 shared 配置

  • type
async function beforeLoadShare(args: BeforeLoadShareOptions): Promise<BeforeLoadShareOptions>  type BeforeLoadShareOptions ={  pkgName: string;  shareInfo?: Shared;  shared: Options['shared'];  origin: ModuleFederation; }

resolveShare

SyncWaterfallHook

允许手动设置实际使用的共享模块。

  • 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

在预加载处理程序执行任何预加载逻辑之前调用

  • type
async function beforePreloadRemote(args: BeforePreloadRemoteOptions): BeforePreloadRemoteOptions  type BeforePreloadRemoteOptions ={  preloadOps: Array<PreloadRemoteArgs>;  options: Options;  origin: ModuleFederation; }

generatePreloadAssets

AsyncHook

用于控制生成需要预加载的资源

  • 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>; }

loaderHook

createScript

SyncHook

用于修改加载资源时的 script

  • 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 === testRemoteEntry) {  let script = document.createElement('script');  script.src = testRemoteEntry;  script.setAttribute('loader-hooks', 'isTrue');  script.setAttribute('crossorigin', 'anonymous');  return script;  }  }  };  };