Acceso al runtime

Lecturas previas

Actualmente, Module Federation ofrece dos formas de registrar y cargar módulos:

  • Una es declararlos en el plugin de build (normalmente en el archivo module-federation.config.ts).

  • La otra es registrar y cargar los módulos directamente mediante la API de runtime.

Los dos modos no entran en conflicto y se pueden usar a la vez. Puedes elegir con flexibilidad el método y el momento de registro de los módulos según tu escenario concreto.

Diferencias entre los dos enfoques

Registrar módulos en runtimeRegistrar módulos en el plugin
Se puede usar sin el plugin de build; el runtime puro sirve directamente para registrar y cargar módulos en proyectos como webpack4El plugin de build requiere webpack5 o superior
Admite el registro dinámico de módulosNo admite el registro dinámico de módulos
No admite cargar módulos con la sintaxis importAdmite cargar módulos con la sintaxis síncrona import
Admite cargar módulos con loadRemoteAdmite cargar módulos con loadRemote
Configurar shared exige proporcionar la versión concreta y la información de la instanciaConfigurar shared solo requiere definir reglas, sin proporcionar la versión concreta ni la información de la instancia
Las dependencias shared solo se pueden ofrecer hacia fuera; no se pueden usar dependencias shared externasLas dependencias shared se comparten en ambos sentidos según reglas concretas
El proceso de carga se puede modificar mediante el mecanismo de plugin del runtimeActualmente no admite proporcionar un plugin para modificar el proceso de carga
No admite sugerencias de tipos remotosAdmite sugerencias de tipos remotos

Si se usa el plugin de build, se creará automáticamente una instancia de MF y se guardará en memoria cuando arranque el proyecto. Puedes llamar directamente a los métodos de la instancia de MF mediante la .

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

loadRemote('remote1');

Si no se usa el plugin de build, tienes que crear manualmente una instancia de MF antes de llamar a la API correspondiente.

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');
Instancia de ModuleFederation

Un objeto creado por la clase ModuleFederation que contiene toda la funcionalidad del runtime. Puedes escribir __FEDERATION__.__INSTANCES__ en la consola para ver la información completa de la instancia.

Instalación

Cada tipo de proyecto debe instalar e importar el Runtime desde una entrada distinta. La mayoría de proyectos deberían instalar @module-federation/enhanced e importar las APIs del Runtime desde @module-federation/enhanced/runtime. Si tu proyecto Modern.js ya usa un plugin de Module Federation, importa las APIs del Runtime desde la entrada /runtime del plugin para que el plugin del framework y las llamadas manuales al Runtime usen la misma instancia del Runtime.

@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';

En proyectos Modern.js v2, instala @module-federation/modern-js e importa las APIs del Runtime desde @module-federation/modern-js/runtime.

Registro de módulos

Plugin de build (con plugin de build)
Runtime puro (sin plugin de build)
// 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',
  }
]);

Carga de módulos

Plugin de build (con plugin de build)
Runtime puro (sin plugin de build)
// 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>
  );
}

Cargar módulos anónimos

Plugin de build (con plugin de build)
Runtime puro (sin plugin de build)
// 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>
  );
}

Cargar módulos con nombre

Plugin de build (con plugin de build)
Runtime puro (sin plugin de build)
// 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>
  );
}

Cargar funciones de utilidad

Plugin de build (con plugin de build)
Runtime puro (sin plugin de build)
// 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);
});

Siguientes lecturas