Concepto clave
La comunicación entre micro-frontends es el mecanismo que permite que aplicaciones independientes, desarrolladas por equipos diferentes, interactóen de forma coordinada. Imagina una ciudad donde cada edificio (micro-frontend) tiene su propia administración, pero necesitan coordinarse para servicios compartidos como el transporte o la seguridad. En arquitecturas de micro-frontends, esta comunicación se logra mediante eventos, APIs compartidas o un estado global, evitando acoplamientos directos que rompan la autonomía de cada equipo.
El desafío principal es mantener el equilibrio entre independencia y colaboración. Sin comunicación, los micro-frontends serían islas aisladas; con demasiada, se convierten en un monolito distribuido. Module Federation de Webpack facilita esto al permitir que los micro-frontends expongan y consuman módulos dinámicamente, pero la lógica de comunicación debe diseñarse cuidadosamente para escalar con múltiples equipos.
Cómo funciona en la práctica
Implementar comunicación efectiva requiere definir un protocolo claro. Un enfoque común es usar un bus de eventos global, donde cada micro-frontend publica y suscribe eventos. Por ejemplo, en una aplicación de e-commerce, el micro-frontend del carrito podría publicar un evento "itemAdded" cuando un producto se añade, y el micro-frontend de recomendaciones lo escucharía para actualizar sugerencias.
Paso a paso: primero, establece un contrato de eventos o APIs compartidas en un módulo federado. Luego, cada micro-frontend importa este módulo para emitir o escuchar eventos. Usa Webpack Module Federation para exponer el bus de eventos desde un host o un micro-frontend designado. Finalmente, implementa manejo de errores y desconexión para evitar fallos en cascada.
Codigo en accion
Aquí un ejemplo de un bus de eventos simple expuesto mediante Module Federation. Primero, el micro-frontend host define y expone el bus:
// host/src/eventBus.js
export class EventBus {
constructor() {
this.listeners = {};
}
on(event, callback) {
if (!this.listeners[event]) this.listeners[event] = [];
this.listeners[event].push(callback);
}
emit(event, data) {
if (this.listeners[event]) {
this.listeners[event].forEach(callback => callback(data));
}
}
}
export const eventBus = new EventBus();En la configuración de Webpack del host, expón este módulo:
// host/webpack.config.js
module.exports = {
// ... otras configuraciones
plugins: [
new ModuleFederationPlugin({
name: 'host',
filename: 'remoteEntry.js',
exposes: {
'./eventBus': './src/eventBus.js',
},
shared: { react: { singleton: true }, 'react-dom': { singleton: true } },
}),
],
};Luego, un micro-frontend remoto lo consume y usa:
// remote/src/App.js
import React, { useEffect } from 'react';
const eventBus = await import('host/eventBus').then(module => module.eventBus);
function App() {
useEffect(() => {
eventBus.on('userLoggedIn', (userData) => {
console.log('Usuario conectado:', userData);
// Actualizar UI basado en el usuario
});
return () => {
// Limpiar listeners al desmontar
};
}, []);
const handleButtonClick = () => {
eventBus.emit('itemAdded', { id: 123, name: 'Producto Ejemplo' });
};
return (
Añadir al carrito
);
}
export default App;Errores comunes
- Acoplamiento excesivo: Evita que los micro-frontends dependan directamente de implementaciones internas de otros. Usa contratos claros (eventos o APIs) y manténlos estables.
- Falta de manejo de errores: Si un micro-frontend falla al emitir o escuchar eventos, puede romper toda la aplicación. Implementa timeouts, reintentos y fallbacks silenciosos.
- Eventos no documentados: Sin documentación, los equipos no sabrán qué eventos están disponibles. Mantén un registro centralizado de eventos y sus payloads.
- Problemas de rendimiento con muchos listeners: Escuchar demasiados eventos puede ralentizar la aplicación. Optimiza usando debouncing o limitando suscripciones a eventos críticos.
- Ignorar la desconexión de micro-frontends: Cuando un micro-frontend se desmonta, debe limpiar sus listeners para evitar memory leaks. Siempre incluye cleanup en useEffect o lifecycle methods.
Checklist de dominio
- He definido un protocolo de comunicación (eventos o APIs) que todos los equipos siguen.
- He implementado un bus de eventos o estado global usando Module Federation para exposición dinámica.
- He añadido manejo de errores y fallbacks para escenarios de red o micro-frontends no disponibles.
- He documentado los eventos y sus estructuras de datos para facilitar la colaboración entre equipos.
- He optimizado el rendimiento limitando listeners y usando técnicas como debouncing donde sea necesario.
- He probado la comunicación en entornos de desarrollo y staging con múltiples micro-frontends.
- He establecido un proceso para evolucionar el protocolo de comunicación sin romper compatibilidad.
Implementa un Sistema de Notificaciones entre Micro-frontends
En este ejercicio, crearás un sistema donde un micro-frontend de notificaciones escuche eventos de otros micro-frontends y muestre alertas en tiempo real. Sigue estos pasos:
- Configura un proyecto con al menos dos micro-frontends usando Webpack Module Federation: uno como host (notifications) y otro como remoto (dashboard).
- En el host, expón un módulo de eventBus similar al ejemplo de código, pero añade un método para registrar notificaciones con prioridad (alta, media, baja).
- En el remoto, consume el eventBus y emite eventos como "taskCompleted" o "errorOccurred" con datos como { message: "Tarea finalizada", priority: "media" }.
- En el host, implementa un componente React que escuche estos eventos y muestre las notificaciones en una lista, aplicando estilos básicos según la prioridad (ej., rojo para alta).
- Añade funcionalidad para cerrar notificaciones y limpiar listeners cuando el componente se desmonte.
- Prueba la comunicación ejecutando ambos micro-frontends y verificando que las notificaciones aparezcan al emitir eventos.
- Usa el patrón de event bus para desacoplar la emisión y recepción de eventos.
- Asegúrate de que la configuración de Module Federation exponga y consuma correctamente el módulo eventBus.
- Considera usar useRef en React para manejar el eventBus sin recrearlo en cada render.
Evalua tu comprension
Completa el quiz interactivo de arriba para ganar XP.