Micro Frontends
Una experiencia, partes con autonomía de entrega
Micro Frontends organiza una experiencia frontend mediante aplicaciones que pueden entregarse con independencia significativa y componerse en un producto mayor. Dividir componentes visuales no basta: importa que una parte pueda cambiar y llegar al usuario sin exigir una entrega coordinada de todas las demás. Esa autonomía siempre tiene contratos y límites.
Cam Jackson, Micro Frontends, publicado en el sitio de Martin Fowler, lo define como un architectural style y también utiliza technique. Destaca aplicaciones frontend entregables independientemente y su composición. El autor es Jackson, no Fowler. kind: concept es clasificación editorial del Atlas para este alcance frontend; no niega la terminología de la fuente ni declara una taxonomía universal.
architecture-profile tiene otro alcance editorial: combina decisiones del sistema sobre varios ejes. Micro Frontends no constituye por sí solo ese perfil completo y no se incorpora por ello al mapa de Profiles. Un sistema puede combinarlo con microservices, modular-monolith u otro backend. «Micro» no fija tamaño, número de pantallas, equipos ni bundles.
Fronteras de experiencia y responsabilidad
En Commerce, Browse, Checkout y Account son candidatos para discutir capacidades visibles y motivos de cambio. Buttons, Forms y CSS describen otros cortes, útiles para bibliotecas, pero no ofrecen automáticamente autonomía sobre experiencias completas. Jackson enfatiza slices verticales de negocio; aquí no se transforma su ejemplo por página en una obligación universal.
boundaries ayuda a preguntar qué responsabilidad queda dentro, quién la mantiene y qué interacción se promete fuera. decomposition identifica unidades y modularity examina relaciones que permiten cambiarlas. Un fragmento con imports privados de todos sus vecinos conserva acoplamiento aunque tenga nombre y pipeline propios.
granularity exige comparar autonomía obtenida con contratos introducidos. Una frontera demasiado amplia puede conservar el bloqueo original; muchas fronteras diminutas pueden convertir un pequeño cambio de checkout en coordinación general. No hay cantidad correcta por aplicación ni regla de un equipo por componente. Una página puede atravesar capacidades y una capacidad abarcar varias rutas.
Entrega, deployment y equipos
Entregable independientemente describe una capacidad de evolución y puesta a disposición. deployment pregunta qué artifacts se instalan o actualizan juntos. En una realización con bundles separados ambas fronteras pueden alinearse; en otra, integración durante build puede vincularlas. Declarar quién debe reconstruir, publicar o activar qué cambio evita convertir deliverable en sinónimo automático de deployment unit.
Autonomía tampoco significa ausencia de coordinación. Cambios compatibles de navegación, identidad, contratos, lenguaje visual o seguridad pueden requerir acuerdos. deployability evalúa facilidad y seguridad de llevar cambios a ejecución; contar pipelines no demuestra esa quality. Si cualquier release exige actualizar simultáneamente todos los participantes, revisar qué independencia se obtuvo realmente.
Los equipos pueden responsabilizarse de una experiencia hasta operación, pero mantienen obligaciones sobre el producto compuesto. Un monorepo puede alojar unidades con entregas independientes; repositorios separados pueden esconder una entrega conjunta. La estructura Git organiza trabajo, no demuestra fronteras arquitectónicas. Ninguna opción exige repartir el backend de la misma manera.
Composición: elegir dónde aparece el compromiso
La experiencia necesita reunir sus partes. Esta tabla compara consecuencias para el ejemplo del Atlas; no establece categorías excluyentes ni una técnica ganadora.
| Composición posible | Qué integra | Compromiso que conviene examinar |
|---|---|---|
| Durante build | Paquetes y versiones seleccionados por un host. | Cambiar una parte puede requerir reconstruir y desplegar el host. |
| En servidor | Páginas, templates o fragmentos. | Disponibilidad, contratos de fragmentos y vigencia del resultado. |
| En runtime cliente | Aplicaciones cargadas y activadas por un contenedor. | Carga, compatibilidad, lifecycle y fallos al integrar. |
| Con iframe | Documentos en contextos de navegación propios. | Aislamiento concreto frente a integración, navegación y experiencia. |
Jackson desaconseja la integración en build que restablece releases lockstep. Conservar esa recomendación no obliga a decidir por el nombre del mecanismo: evaluar si una publicación nueva puede llegar realmente sin reinstalar todas las partes. Un paquete actualizado independientemente todavía puede necesitar que otro equipo lo consuma y publique.
Componer en servidor tampoco equivale universalmente a SSR por request: puede reunir fragmentos previamente generados o representaciones producidas en otros momentos. rendering-strategies conserva la pregunta de dónde y cuándo se produce representación. Integración y rendering son dimensiones relacionadas; una no determina toda la otra.
Mecanismos concretos sin convertirlos en definición
Webpack Module Federation distingue módulos locales del build y módulos remotos cargados desde containers en runtime. Puede realizar colaboración entre aplicaciones, pero usarlo no prueba que sus responsabilidades o releases sean independientes. Un import remoto sigue creando una dependencia cuyo contrato y disponibilidad deben comprenderse.
Web Components ofrece mecanismos del navegador para elementos y encapsulación; también sirve en aplicaciones sin Micro Frontends. No prescribe equipos, deployment ni autoridad de negocio. MDN documenta iframe como contexto de navegación anidado: su origen, permisos y sandbox condicionan el aislamiento efectivo. No todo iframe aporta la misma frontera de seguridad.
Un iframe puede ser apropiado cuando importa separar contextos, aceptando dificultades de tamaño, foco, accesibilidad, comunicación e historial. No corresponde descartarlo por poco moderno. Module Federation, Web Components e iframes son opciones con compromisos distintos, no requisitos acumulativos ni sustitutos de definir la experiencia y sus contratos.
Shell y routing sin concentrar todo
Muchas realizaciones usan un shell o container para layout general, navegación, localización y activación de aplicaciones. Puede iniciar telemetría o transmitir contexto de sesión. Precisar qué pertenece globalmente evita que Checkout termine siendo una vista pasiva de toda la lógica comercial acumulada en el shell.
El contrato de activación necesita explicar qué recibe una parte, cómo señala errores y cuándo libera recursos. Si una ruta deja de estar activa, listeners o trabajo abandonado pueden seguir afectando a vecinos. La frontera de ownership tiene que seguir existiendo durante montaje, reemplazo y retirada, no solo en el repositorio.
Routing puede vivir en el shell, delegarse bajo una ruta o combinar niveles. Importan enlaces profundos, historial, parámetros y rutas desconocidas. Un cambio de Checkout que rompe enlaces desde Account es un cambio de integración aunque ambos bundles compilen. No hay jerarquía obligatoria de routers ni necesidad de un shell propietario de toda decisión.
Comunicación y estado que cruzan fronteras
URL, mensajes, eventos, contratos explícitos, estado compartido y colaboración mediante backend son posibilidades. communication pregunta cómo intercambian información. Importar internals del vecino puede ahorrar trabajo inmediato y volver imposible cambiarlo por separado; prohibir cualquier comunicación tampoco produce una experiencia útil. Hacer visibles productores, consumidores y expectativas temporales permite discutir el compromiso.
Un event bus global puede ocultar referencias directas mientras introduce consumidores desconocidos, dependencia del orden y debugging difícil. Cambiar CartUpdated sin conocer quién lo interpreta no se vuelve seguro por usar publicación/suscripción. Un mensaje también tiene contrato; «desacoplado» necesita una dimensión y evidencia.
La guía de single-spa recomienda en su contexto evitar un store global que vincule aplicaciones. El Atlas conserva esa cautela sin prohibir universalmente compartir estado. client-state-management aporta ownership, scope, lifecycle y vigencia: preguntar qué dato necesita cruzar, quién escribe y cómo se termina su uso. Copias de precio o sesión tampoco transfieren autoridad comercial.
Tecnologías, diseño y dependencias compartidas
Distintos frameworks pueden facilitar sustitución gradual, pero no son condición ni objetivo. Usar el mismo framework en todas las partes puede reducir el trabajo de compatibilidad y formación; mezclar runtimes puede ampliar descarga, skills y modos de fallo. La elección debe responder a necesidades reales, sin celebrar diversidad tecnológica como madurez.
Un design system puede sostener coherencia visual y de interacción. Una biblioteca de botones no es una Micro Frontend y su mantenimiento central no requiere centralizar cada feature. accessibility exige que landmarks, foco y anuncios sigan siendo utilizables al componer partes; internationalization necesita contexto de locale, dirección y fallback compatible. Navegación y analytics también atraviesan el producto: separar equipos no hace aceptable que cada fragmento imponga una experiencia incompatible.
Compartir dependencias puede ahorrar bytes y exigir coordinación de versiones; duplicarlas puede permitir evolución separada y aumentar payload. La documentación de single-spa examina ese compromiso para sus dependencias compartidas. Requisitos estrictos de singleton pueden reducir libertad aunque los deployments estén separados. No hay regla de compartir siempre React ni de duplicar todo para aparentar autonomía.
Fallos, pruebas y operación de la experiencia
Separar bundles no demuestra isolation. Un error global, shell caído, dependencia compartida incompatible o agotamiento del runtime puede afectar varias partes. Fronteras de error ayudan según realización; código que ejecuta con los mismos privilegios del documento no obtiene una barrera de confianza por llamarse otra aplicación.
Las pruebas aisladas necesitan complementarse con contratos, integración y recorridos completos. Browse puede agregar un producto correctamente y Checkout interpretar mal su identidad. Durante rollout pueden coexistir versiones: probar solo el conjunto más reciente deja sin evidencia combinaciones válidas de producción. El versionado debe sostener compatibilidad necesaria, sin imponer SemVer a cada frontera.
Por ejemplo, un browser conserva el shell anterior mientras Checkout acaba de publicarse. Hay que explicar cómo encuentra una versión compatible, qué ocurre si falla su descarga y cuánto tiempo siguen disponibles los assets que necesita. Publicar archivos correctamente no prueba que una sesión ya abierta pueda usarlos. Otra sesión puede cargar una combinación diferente sin que exista un incidente, siempre que ambas combinaciones estén soportadas.
La recuperación requiere el mismo análisis: volver a un bundle anterior puede recuperar representación y no deshacer un pago ya solicitado. Si el contrato del backend cambió, restaurar únicamente el frontend podría no recuperar el recorrido. Identificar qué versiones, datos y efectos participan permite preparar una respuesta concreta, en lugar de prometer rollback independiente por disponer de archivos separados.
operability requiere identificar aplicación, versión y responsable en una experiencia compuesta. Más unidades pueden agregar rollout, diagnósticos, incidentes y gobierno. Duplicación de librerías, peticiones y coordinación de startup pueden afectar rendimiento, sin implicar lentitud inevitable. web-performance aporta evaluación field/lab de ese costo real; compartir dependencias puede reducir duplicación a cambio de coordinación que limite autonomía. Aquí interesa qué costo crea la composición y quién puede explicarlo.
Commerce: fronteras distintas que colaboran
Supongamos que Browse, Checkout y Account evolucionan con responsables y cadencias diferentes. Checkout solicita capacidades de Orders, Payments e Inventory; no necesita un Payments MFE por existir Payments Service. El corte responde a la experiencia, mientras el backend conserva su propio reparto de autoridad. También sería posible mantener esas capacidades en un monolito.
Todas las partes Web podrían llamar a un backend-for-frontend común que adapte información para esa experiencia. Otra organización podría justificar varias adaptaciones. MFE, BFF y dominio backend no tienen correspondencia uno a uno: separar uno no decide el número de los otros ni obliga a compartir datos privados.
Dentro de Checkout podrían usarse presentation-patterns y unidirectional-data-flow; otra parte podría organizar presentación de otro modo. No son alternativas a Micro Frontends. Rendering por ruta o región puede variar si la plataforma lo admite, pero aumenta combinaciones que integrar. La coherencia del pago y de la experiencia sigue siendo responsabilidad del producto.
Migración y criterio de adopción
Como ejemplo propio, Commerce podría extraer Account primero por una ruta clara, poco estado transversal y necesidad de entrega independiente. strangler-fig ofrece un desplazamiento incremental mientras convive el frontend anterior; no es una secuencia universal. refactor-vs-rewrite evita deducir que adoptar Micro Frontends exige reescribir todo. Hay que comprobar navegación, contratos y retirada del camino sustituido.
Puede ser útil cuando el costo de coordinar cambios entre responsables supera sostenidamente el de componer aplicaciones. Puede resultar innecesario para un equipo pequeño, una superficie muy acoplada o poca necesidad de releases independientes. Sin automatización y acuerdos, fragmentar puede multiplicar esperas. No existe umbral numérico de equipos ni escalera de madurez.
El beneficio buscado es autonomía útil con una experiencia coherente. Contrastar un cambio real: qué parte cambia, qué otros releases exige, qué falla y quién lo opera. accidental-complexity permite evaluar si la separación reduce problemas o los desplaza. frontend-and-client-architecture conecta estas preguntas con estado y rendering, sin convertir más aplicaciones en prueba de mejor arquitectura.