Runtime Access

Prerequisite reading

Currently, Module Federation provides two ways to register and load modules:

  • One is to declare it in the build plugin (usually in the module-federation.config.ts file).

  • The other way is to directly register and load modules through the runtime API.

The two modes are not conflicting and can be used together. You can flexibly choose the module registration method and timing according to your actual scenario.

Differences between the two approaches

Registering modules at runtimeRegistering modules in the plugin
Can be used without the build plugin, and pure runtime can be used directly for module registration and loading in projects like webpack4The build plugin needs to be webpack5 or above
Supports dynamic module registrationDoes not support dynamic module registration
Does not support loading modules with import syntaxSupports loading modules with import synchronous syntax
Supports loading modules with loadRemoteSupports loading modules with loadRemote
Setting shared must provide specific version and instance informationSetting shared only requires configuring rules, without providing specific version and instance information
shared dependencies can only be used externally, and external shared dependencies cannot be usedshared dependencies are shared bidirectionally according to specific rules
The loading process can be affected through the runtime's plugin mechanismCurrently does not support providing plugin to affect the loading process
Does not support remote type hintsSupports remote type hints

If the build plugin is used, an MF instance will be automatically created and stored in memory when the project starts. You can directly call methods of the MF instance via the .

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

loadRemote('remote1');

If the build plugin is not used, you need to manually create an MF instance before calling the corresponding API.

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

const mf = createInstance({
  name: 'host',
  remotes: [
    {
      name: 'remote1',
      entry: 'http://localhost:2001/vmok-manifest.json',
    },
  ],
});

mf.loadRemote('remote1');
ModuleFederation instance

An object created by the ModuleFederation class that contains all runtime functionality. You can enter __FEDERATION__.__INSTANCES__ in the console to view the full instance information.

Installation

Different project types should install and import Runtime from different entries. Most projects should install @module-federation/enhanced and import Runtime APIs from @module-federation/enhanced/runtime. If your Modern.js project already uses a Module Federation plugin, import Runtime APIs from the plugin's /runtime entry so the framework plugin and manual Runtime calls use the same Runtime instance.

@module-federation/enhanced

npm
yarn
pnpm
bun
npm install @module-federation/enhanced --save
import { createInstance, loadRemote } from '@module-federation/enhanced/runtime';

Modern.js

npm
yarn
pnpm
bun
npm install @module-federation/modern-js-v3 --save
import { createInstance, loadRemote } from '@module-federation/modern-js-v3/runtime';

For Modern.js v2 projects, install @module-federation/modern-js and import Runtime APIs from @module-federation/modern-js/runtime.

Module Registration

Build Plugin(Use build plugin)
Pure Runtime(Not use build plugin)
// If use build plugin, you can use `registerRemotes` directly.
import { registerRemotes } from '@module-federation/enhanced/runtime';

registerRemotes([
  {
      name: 'remote1',
      alias: 'remote-1',
      entry: 'http://localhost:3001/mf-manifest.json',
  }
]);

Module Loading

Build Plugin(Use build plugin)
Pure Runtime(Not use build plugin)
// If use build plugin, you can use `loadRemote` directly.
import { loadRemote } from '@module-federation/enhanced/runtime';
import React from 'react';

export default () => {
  const MyButton = React.lazy(() =>
    loadRemote('remote1').then(({ MyButton }) => {
      return {
        default: MyButton
      };
    }),
  );

  return (
    <React.Suspense fallback="Loading Button">
      <MyButton />
    </React.Suspense>
  );
}

Loading Anonymous Modules

Build Plugin(Use build plugin)
Pure Runtime(Not use build plugin)
// If use build plugin, you can use `loadRemote` directly.
import React from 'react';
import { loadRemote } from '@module-federation/enhanced/runtime';

const RemoteButton = React.lazy(() => loadRemote('provider/button'));
// 也可通过模块别名加载:
// const RemoteButton = React.lazy(() => loadRemote('remotes-1/button'));

export default () => {
  return (
    <React.Suspense fallback="Loading Button">
      <RemoteButton />
    </React.Suspense>
  );
}

Loading Named Modules

Build Plugin(Use build plugin)
Pure Runtime(Not use build plugin)
// If use build plugin, you can use `loadRemote` directly.
import React from 'react';
import { loadRemote } from '@module-federation/enhanced/runtime';

export default () => {
  const RemoteButton = React.lazy(() =>
    loadRemote('remote1/button').then(({ RemoteButton }) => {
      return {
        default: RemoteButton
      };
    }),
  );
  return (
    <React.Suspense fallback="Loading Button">
      <RemoteButton />
    </React.Suspense>
  );
}

Loading Utility Functions

Build Plugin(Use build plugin)
Pure Runtime(Not use build plugin)
// If use build plugin, you can use `loadRemote` directly.
import React from 'react';
import { loadRemote } from '@module-federation/enhanced/runtime';

// 加载 remote1 expose 的 util
loadRemote<{add: (...args: Array<number>)=> number }>("remote1/util").then((md)=>{
    md.add(1,2);
});