wandres.dev
MODULE FEDERATION · microfrontends

Microfrontends: equipos que despliegan solos

Module Federation es una técnica; los microfrontends son la arquitectura. La idea de fondo es organizativa: cada equipo posee un trozo de la interfaz y lo despliega a su ritmo, sin coordinar una release monolítica. Cada microfrontend se publica como un paquete versionado en una URL estable, y una app shell los compone. Aquí, las estrategias de composición y por qué Conway lo explica todo.

⏱ 18 min

Es tentador confundir Module Federation con los microfrontends, pero son cosas de distinto orden. Module Federation es una técnica de integración en runtime; los microfrontends son una arquitectura, y su motivación no es técnica sino organizativa: permitir que muchos equipos posean cada uno un trozo de la interfaz y lo desplieguen a su propio ritmo, sin sincronizar una release única y monolítica. Cada microfrontend se comporta como un paquete versionado, publicado en una URL estable, y una app shell los compone en la pantalla del usuario.

🎯 Al terminar esta lección sabrás
  • Separar la técnica (Module Federation) de la arquitectura (microfrontends) que la usa.
  • Entender el despliegue independiente como el verdadero objetivo, y a Conway como su explicación.
  • Ver cada microfrontend como un paquete versionado con una URL y un contrato estables.
  • Comparar las estrategias de composición: en build, en el servidor y en runtime.

De una técnica a una arquitectura

Un microfrontend es la extensión al frontend de la idea de microservicio: partir una aplicación grande en piezas que equipos distintos desarrollan, prueban y despliegan por separado. Module Federation es una de las formas de implementarlo, pero no la única: hay microfrontends montados con iframes, con Web Components, con import maps, con composición en el borde. La técnica es intercambiable; la arquitectura es la decisión de fondo.

Y esa decisión es, ante todo, organizativa. La ley de Conway dice que la arquitectura de un sistema tiende a copiar la estructura de comunicación de la organización que lo construye. Los microfrontends son la aplicación deliberada de ese principio: si tienes ocho equipos autónomos, en lugar de forzarlos a compartir un monolito donde se pisan en cada release, les das a cada uno una frontera de despliegue propia que refleje su autonomía real.

📝
Conway no es una anécdota, es el criterio

La pregunta que decide si necesitas microfrontends no es técnica —cuántas líneas tiene tu app, qué framework usas— sino organizativa: cuántos equipos independientes necesitan desplegar a la interfaz sin coordinarse entre sí. Si la respuesta es uno, no tienes un problema de microfrontends por mucho que tu app crezca. Si son ocho equipos peleándose por una cola de despliegue única, ninguna cantidad de refactor interno te dará lo que te daría partir la frontera de despliegue.

Despliegue independiente: el verdadero objetivo

Todo lo demás en los microfrontends es medio; el fin es el despliegue independiente. Un equipo que posee el microfrontend de búsqueda debe poder arreglar un bug, construir su artefacto y publicarlo en producción sin recompilar ni redeplegar el resto de la aplicación, y sin esperar a la ventana de release de nadie. Ese es el valor que justifica toda la complejidad que veremos en la próxima lección.

Aquí es donde encaja Module Federation: al integrar en runtime, permite que cada equipo despliegue su remote en su URL cuando quiera, y que la app shell recoja la versión nueva en la siguiente carga. Sin integración en runtime, la independencia se evapora: si componer requiere recompilar el contenedor, has vuelto al monolito con pasos extra.

flowchart TD
Shell[app shell orquesta la pantalla] --> A[mfe busqueda equipo A]
Shell --> B[mfe catalogo equipo B]
Shell --> C[mfe carrito equipo C]
A -->|despliega solo| DA[pipeline A]
B -->|despliega solo| DB[pipeline B]
C -->|despliega solo| DC[pipeline C]
style Shell fill:#cba6f7,color:#11111b
style A fill:#89b4fa,color:#11111b
style B fill:#a6e3a1,color:#11111b
style C fill:#f9e2af,color:#11111b

Cada microfrontend como paquete versionado

Para que un equipo consuma el trabajo de otro sin acoplarse a su código fuente, cada microfrontend se comporta como un paquete versionado: publica un artefacto —su manifiesto y sus chunks— en una URL estable, con un contrato claro de qué expone. La app shell no conoce el código del microfrontend; conoce su URL y su API pública, igual que un consumidor de una librería conoce su interfaz y no sus entrañas.

El versionado de esa URL es una decisión de diseño con consecuencias. Apuntar a una URL de última versión da despliegue instantáneo pero ninguna red de seguridad: el nuevo remote llega a todos a la vez. Versionar la URL —incluir un número o un hash— permite despliegues graduales, rollbacks y que la shell fije qué versión de cada microfrontend compone, a cambio de un paso de promoción explícito.

// La shell registra cada microfrontend por su URL versionada.
registerRemotes([
  { name: "busqueda", entry: "https://cdn.example.com/busqueda/v4/mf-manifest.json" },
  { name: "catalogo", entry: "https://cdn.example.com/catalogo/v9/mf-manifest.json" },
  { name: "carrito", entry: "https://cdn.example.com/carrito/v2/mf-manifest.json" },
]);
📦

Composición en build

Cada microfrontend es un paquete que la shell instala y empaqueta. Simple y con tipos, pero cada cambio obliga a redeplegar la shell: no hay despliegue independiente real.

🌐

Composición en el servidor

El servidor o el borde ensambla el HTML de varios equipos con inclusiones del lado del servidor. Buen rendimiento inicial, a cambio de infraestructura de composición.

Composición en runtime

El navegador integra las piezas con Module Federation, Web Components o import maps. Es la que da despliegue independiente pleno, con el coste de mover fallos al runtime.

Las estrategias de composición

Las tres tarjetas anteriores marcan un eje: cuándo se ensamblan las piezas. En build, integras al compilar la shell —tienes tipos y verificación, pero pierdes la independencia, porque cada cambio de un microfrontend recompila el contenedor—. En el servidor, ensamblas HTML de varios orígenes en el borde, con buen tiempo de primer pintado. En runtime, integras en el navegador, que es lo que da la independencia plena a costa de la fragilidad de la red. Module Federation vive en esta tercera casilla, y por eso arrastra tanto sus virtudes como sus peligros.

El panorama de 2026 ofrece varias encarnaciones de la idea. single-spa orquesta microfrontends de frameworks distintos bajo un router común; Piral añade un modelo de portal con pilets; Native Federation implementa la composición en runtime con import maps y ESM estándar, sin atarse a un bundler; y Module Federation 2.0 sobre Rspack es la vía más integrada cuando todos los equipos comparten toolchain. Todas resuelven el mismo problema organizativo con distintos compromisos técnicos.

ℹ️
El design system es el pegamento invisible

Una malla de microfrontends desplegados por equipos distintos corre el riesgo de verse como una colcha de retales: cada trozo con su tipografía, sus botones, su espaciado. El antídoto es un design system compartido —normalmente un paquete versionado más una dependencia shared— que garantice coherencia visual sin recentralizar el desarrollo. Sin él, la independencia de despliegue se paga en incoherencia de producto, y el usuario nota las costuras.

Los microfrontends resuelven un problema de personas, no de código

El error más común y más caro con los microfrontends es adoptarlos como una mejora técnica, cuando son una respuesta a un problema humano. Ninguna aplicación necesita microfrontends por ser grande, por ser lenta o por usar varios frameworks; los necesita, si acaso, porque muchos equipos autónomos chocan al desplegar sobre una misma base de código y esa fricción se ha vuelto más cara que la complejidad de partirla. La ley de Conway no es aquí una curiosidad de manual, sino el criterio de decisión: la arquitectura del sistema va a reflejar la estructura de tu organización lo quieras o no, y los microfrontends son simplemente la elección de hacer ese reflejo explícito y deliberado en lugar de sufrirlo como accidente. De ahí se sigue todo lo demás. La razón por la que la composición en runtime importa es que sin ella el despliegue independiente es ficticio, y sin despliegue independiente no hay ninguna ganancia que compense el coste. La razón por la que cada microfrontend se versiona como un paquete es que los equipos necesitan un contrato estable entre ellos, no acceso al código ajeno. La razón por la que un design system compartido es casi obligatorio es que la autonomía técnica no puede comprarse al precio de la incoherencia del producto que ve el usuario. Todas estas piezas encajan solo cuando entiendes que la unidad de diseño no es el componente ni el bundle, sino el equipo y su capacidad de avanzar sin pedir permiso. Por eso la prueba definitiva de si necesitas esta arquitectura no está en un diagrama de cajas, sino en una pregunta sobre personas: ¿tienes de verdad varios equipos que se estorban al desplegar? Si no, casi cualquier problema que creas resolver con microfrontends lo resuelve mejor un monolito bien modularizado, y sin la factura de operar una constelación de despliegues.

⚔️ Piensa como una organización, no como un grafo
  1. Dibuja tu organización —equipos y quién despliega qué— y superpón encima dónde caerían las fronteras de microfrontend.
  2. Monta una app shell que registre dos microfrontends por URL versionada y componga ambos en una misma pantalla.
  3. Despliega una versión nueva de uno de ellos cambiando solo su URL en la shell, sin tocar el otro, y confirma la independencia.
  4. Extrae un botón a un design system compartido como dependencia shared y comprueba que ambos microfrontends lo usan igual.
  5. Argumenta en un párrafo, para un producto que conozcas, si Conway justifica microfrontends o si un monolito modular basta.