Concepto clave
En Module Federation, el host es la aplicación principal que consume módulos remotos, mientras que el remoto es la aplicación que expone módulos para ser consumidos. Piensa en el host como un centro comercial que alquila espacios a tiendas independientes (remotos). El host integra estos módulos en tiempo de ejecución, permitiendo que equipos diferentes desarrollen y desplieguen partes de la aplicación de forma autónoma.
La relación host-remoto es dinámica y puede ser bidireccional: una aplicación puede actuar como host para algunos módulos y como remoto para otros. Esto es clave en arquitecturas de micro-frontends, donde múltiples equipos colaboran sin acoplamiento directo. La configuración define qué módulos se exponen y cómo se consumen, creando un ecosistema distribuido pero cohesionado.
Cómo funciona en la práctica
Imagina que tienes una aplicación de e-commerce (host) que necesita un carrito de compras desarrollado por otro equipo (remoto). Primero, el equipo del remoto configura su webpack para exponer el módulo del carrito. Luego, el host configura su webpack para consumir ese módulo remoto. En tiempo de ejecución, el host carga dinámicamente el carrito desde el remoto, como si fuera parte de su propio código.
Paso a paso: 1) El remoto define en su webpack.config.js qué módulos expone. 2) El host define en su webpack.config.js qué remotos consume. 3) Durante el build, Webpack genera manifiestos que describen los módulos disponibles. 4) En runtime, el host usa estos manifiestos para cargar los módulos remotos bajo demanda. Esto permite actualizaciones independientes: si el remoto despliega una nueva versión del carrito, el host la recibe automáticamente sin redeploy.
Codigo en accion
Configuración del remoto (carrito de compras):
// webpack.config.js del remoto
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');
module.exports = {
// ... otras configuraciones
plugins: [
new ModuleFederationPlugin({
name: 'cartApp',
filename: 'remoteEntry.js',
exposes: {
'./Cart': './src/components/Cart',
'./CartSummary': './src/components/CartSummary'
},
shared: ['react', 'react-dom']
})
]
};
Configuración del host (aplicación principal):
// webpack.config.js del host
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');
module.exports = {
// ... otras configuraciones
plugins: [
new ModuleFederationPlugin({
name: 'hostApp',
remotes: {
cart: 'cartApp@http://localhost:3001/remoteEntry.js'
},
shared: ['react', 'react-dom']
})
]
};
Uso en el host para cargar el módulo remoto:
// En un componente del host
import React, { useEffect, useState } from 'react';
const CartComponent = () => {
const [Cart, setCart] = useState(null);
useEffect(() => {
import('cart/Cart')
.then(module => setCart(() => module.default))
.catch(err => console.error('Error cargando el carrito:', err));
}, []);
if (!Cart) return Cargando carrito...;
return ;
};
export default CartComponent;
Errores comunes
- Error 1: No compartir dependencias correctamente. Si host y remoto usan versiones diferentes de React, puede causar errores de runtime. Solución: Usa el campo shared en ambos para alinear versiones.
- Error 2: Configurar mal las URLs de los remotos. Usar localhost en producción romperá la carga. Solución: Usa variables de entorno para manejar URLs dinámicamente.
- Error 3: Exponer módulos demasiado granulares o acoplados. Esto aumenta la complejidad. Solución: Expone módulos cohesivos y con interfaces claras.
- Error 4: Olvidar manejar estados de carga y error en los imports dinámicos. Solución: Siempre incluye manejo de promesas y fallbacks.
- Error 5: No versionar los remotos, causando breaks en el host. Solución: Implementa versionado semántico y pruebas de integración.
Checklist de dominio
- Puedo configurar un remoto que exponga al menos dos módulos funcionales.
- Puedo configurar un host que consuma múltiples remotos desde diferentes orígenes.
- Entiendo cómo el campo shared evita conflictos de dependencias.
- Sé depurar errores comunes como "Module not found" en remotos.
- Puedo explicar la diferencia entre build time y runtime en Module Federation.
- Implemento manejo de errores y loading states en imports dinámicos.
- Diseño interfaces estables entre host y remotos para minimizar acoplamiento.
Configura un ecosistema host-remoto con Module Federation
En este ejercicio, crearás una configuración práctica de Module Federation con un host y dos remotos. Sigue estos pasos:
- Crea tres proyectos independientes usando Create React App o una configuración similar: uno para el host (puerto 3000), y dos para remotos (puertos 3001 y 3002).
- En cada remoto, configura webpack con ModuleFederationPlugin para exponer un módulo simple (ej., un componente de botón o un servicio). Asegúrate de usar el campo shared para React.
- En el host, configura webpack para consumir ambos remotos. Define las URLs correctas en el campo remotes.
- En el host, implementa un componente que cargue dinámicamente módulos de ambos remotos y los renderice en la interfaz.
- Prueba la configuración ejecutando las aplicaciones y verificando que los módulos se carguen sin errores. Modifica un remoto y observa cómo el host refleja los cambios sin redeploy.
- Usa la biblioteca webpack-module-federation para simplificar la configuración si es necesario.
- Asegúrate de que los puertos no entren en conflicto y que las URLs en remotes sean accesibles.
- Prueba con dependencias compartidas diferentes, como una librería de UI, para ver cómo se manejan.
Evalua tu comprension
Completa el quiz interactivo de arriba para ganar XP.