Desarrollo y despliegue de microfrontends con single-spa
Frontend

Desarrollo y despliegue de microfrontends con single-spa

3 October 2026 · 11 min de lectura
Home / Frontend / Desarrollo y despliegue de microfrontends con single-spa

Introduccion a la arquitectura de microfrontends

La arquitectura de microfrontends aplica los principios de los microservicios al desarrollo del lado del cliente. En lugar de mantener una unica aplicacion monolítica, el frontend se divide en piezas independientes que pueden construirse, probarse y desplegarse por separado. Cada equipo puede elegir su propio marco de trabajo, ciclo de liberacion y estrategia de pruebas, siempre que respete un contrato de integracion comun.

En 2026 esta aproximacion sigue siendo relevante para organizaciones con multiples equipos que trabajan sobre la misma experiencia de usuario. Herramientas como single-spa, Module Federation y Native Federation ofrecen distintos niveles de composicion en tiempo de ejecucion. single-spa destaca por su neutralidad respecto al framework: permite que aplicaciones React, Vue, Angular o incluso vanilla JavaScript coexistán en la misma pagina bajo un unico enrutador y un ciclo de vida controlado.

El valor principal no reside en la novedad tecnica, sino en la autonomia organizativa. Cuando un cambio en la barra de navegacion no obliga a redesplegar todo el catalogo de productos, los equipos reducen la friccion de coordinacion y aceleran la entrega de valor. Al mismo tiempo, aparecen nuevos desafios: gestion de dependencias compartidas, aislamiento de estilos, observabilidad transversal y consistencia de la experiencia de usuario.

Este articulo detalla el proceso completo de creacion, registro, estilo y despliegue de una aplicacion compuesta por varios microfrontends utilizando single-spa. Se actualizan las recomendaciones a las practicas vigentes en 2026 y se incluyen ejemplos de codigo que pueden reproducirse paso a paso.

Conceptos fundamentales de single-spa

single-spa es un framework de orquestacion que registra aplicaciones frontend y decide cuando deben montarse o desmontarse segun la ruta actual o cualquier otra condicion. Cada aplicacion registrada expone tres metodos de ciclo de vida: bootstrap, mount y unmount. El contenedor principal, conocido como root config, invoca estos metodos en el momento adecuado.

Existen tres tipos de entidades en el ecosistema single-spa. Las applications estan ligadas a rutas y representan secciones completas de la interfaz. Los parcels son componentes reutilizables que pueden montarse en cualquier lugar sin depender de la ruta. Los utility modules exportan logica compartida, como clientes de API o stores, sin renderizar interfaz.

La recomendacion actual de los mantenedores es preferir applications basadas en rutas frente a parcels cuando sea posible. Las transiciones entre rutas suelen destruir la mayor parte del estado de la interfaz, por lo que la necesidad de compartir estado entre microfrontends se reduce de forma natural. Esta decision simplifica el diseno y mejora el aislamiento.

El mecanismo de carga se basa en SystemJS o en mapas de importacion nativos. Cada microfrontend se publica como un modulo JavaScript que el navegador puede cargar de forma dinamica. El root config declara en un import map la ubicacion de cada modulo, lo que permite cambiar la version desplegada sin reconstruir el contenedor.

Creacion del contenedor principal

El punto de partida es generar el root config con la herramienta oficial create-single-spa. Esta CLI produce una estructura minima que incluye el archivo de registro de aplicaciones y la plantilla HTML.

mkdir single-spa-demo
cd single-spa-demo
mkdir single-spa-demo-root-config
cd single-spa-demo-root-config
npx create-single-spa

Durante el asistente se selecciona la opcion single spa root config y se indica el nombre de la organizacion. El resultado es un proyecto listo para registrar aplicaciones hijas. El archivo principal de configuracion importa las funciones de registro y arranque:

import { registerApplication, start } from "single-spa";
import * as isActive from "./activity-functions";

registerApplication(
    "@org/single-spa-demo-nav",
    () => System.import("@org/single-spa-demo-nav"),
    isActive.nav
);

registerApplication(
    "@org/single-spa-demo-page-1",
    () => System.import("@org/single-spa-demo-page-1"),
    isActive.page1
);

registerApplication(
    "@org/single-spa-demo-page-2",
    () => System.import("@org/single-spa-demo-page-2"),
    isActive.page2
);

start();

Cada llamada a registerApplication recibe el nombre del modulo, una funcion de carga y una funcion de actividad que determina si la aplicacion debe estar activa. Opcionalmente se puede indicar el elemento del DOM donde debe montarse, lo que evita problemas de orden de renderizado.

Definicion de las funciones de actividad

Las activity functions son predicados que reciben el objeto location y devuelven un valor booleano. Cuando el valor es verdadero, single-spa monta la aplicacion correspondiente; cuando es falso, la desmonta.

export function prefix(location, ...prefixes) {
    return prefixes.some(
        (prefix) => location.href.indexOf(`${location.origin}/${prefix}`) !== -1
    );
}

export function nav() {
    return true;
}

export function page1(location) {
    return prefix(location, "page1");
}

export function page2(location) {
    return prefix(location, "page2");
}

La barra de navegacion permanece siempre activa. Las paginas se activan unicamente cuando la ruta contiene el prefijo correspondiente. Este enfoque basado en prefijos es simple y suficiente para la mayoria de los casos. En aplicaciones mas complejas se pueden combinar condiciones de ruta con estados de autenticacion o caracteristicas del usuario.

Generacion de los microfrontends individuales

Cada microfrontend se crea de forma independiente con la misma CLI, seleccionando la opcion single-spa application / parcel y el framework deseado. En el ejemplo se utiliza React, aunque el proceso es analogo para Vue o Angular.

cd ..
mkdir single-spa-demo-nav
cd single-spa-demo-nav
npx create-single-spa

Se repite el proceso para page-1 y page-2, manteniendo el mismo nombre de organizacion. Cada proyecto genera su propio bundle y expone los metodos de ciclo de vida requeridos por single-spa. En el caso de React, la libreria single-spa-react se encarga de adaptar el componente raiz a dichos metodos.

El componente raiz de la barra de navegacion puede incluir enlaces que modifican la ruta:

import React from "react";
import "./root.component.css";

export default function Root() {
    return (
        <nav className="nav">
            <a href="/page1" className="link">
                Pagina 1
            </a>
            <a href="/page2" className="link">
                Pagina 2
            </a>
        </nav>
    );
}

Los estilos se mantienen aislados mediante hojas de estilo propias de cada microfrontend. Cuando se necesita compartir tokens de diseno, la practica recomendada en 2026 es publicar un paquete de tokens versionado que cada equipo consume como dependencia.

Configuracion del mapa de importacion local

Durante el desarrollo local cada aplicacion corre en su propio puerto. El root config declara estas ubicaciones en un import map condicional:

<% if (isLocal) { %>
<script type="systemjs-importmap">
    {
        "imports": {
            "@org/root-config": "http://localhost:9000/root-config.js",
            "@org/single-spa-demo-nav": "http://localhost:9001/org-single-spa-demo-nav.js",
            "@org/single-spa-demo-page-1": "http://localhost:9002/org-single-spa-demo-page-1.js",
            "@org/single-spa-demo-page-2": "http://localhost:9003/org-single-spa-demo-page-2.js"
        }
    }
</script>
<% } %>

Para arrancar el entorno se abren cuatro terminales y se ejecuta el servidor de desarrollo de cada proyecto en el puerto asignado. Al navegar a localhost:9000 se observa la composicion de las aplicaciones segun la ruta activa.

Montaje controlado en contenedores DOM

Sin un contenedor explicito, el orden de montaje depende de la velocidad de descarga de cada bundle. Para garantizar un layout predecible se definen elementos destino en el HTML del root config:

<div id="nav-container"></div>
<main>
    <div id="page-1-container"></div>
    <div id="page-2-container"></div>
</main>

Y se pasan como cuarto argumento a registerApplication:

registerApplication(
    "@org/single-spa-demo-nav",
    () => System.import("@org/single-spa-demo-nav"),
    isActive.nav,
    { domElement: document.getElementById("nav-container") }
);

De esta forma cada microfrontend se inserta siempre en la misma ubicacion del arbol DOM, independientemente del tiempo de carga.

Estilos y aislamiento visual

Cada microfrontend debe encargarse de sus propios estilos para evitar colisiones. El uso de CSS Modules, Shadow DOM o convenciones de nomenclatura basadas en el nombre de la aplicacion reduce el riesgo de fugas de estilos. En el ejemplo se aplican clases simples:

.nav {
    display: flex;
    flex-direction: row;
    padding: 20px;
    background: #000;
    color: #fff;
}

.link {
    margin-right: 20px;
    color: #fff;
    text-decoration: none;
}

.link:hover,
.link:focus {
    color: #1098f7;
}

Cuando varios equipos deben compartir un sistema de diseno, la estrategia mas segura es publicar los tokens y los componentes primitivos como paquetes npm versionados. Cada microfrontend declara la version exacta que utiliza, lo que permite actualizaciones graduales sin forzar un redespliegue sincronizado de toda la plataforma.

Despliegue independiente y pipeline de CI

Una de las ventajas centrales de los microfrontends es la capacidad de desplegar una pieza sin afectar a las demas. El flujo tipico consiste en construir el bundle de cada aplicacion y subirlo a un almacenamiento de objetos como S3 o a un CDN. El import map de produccion apunta a las URLs publicas de esos bundles.

Un pipeline de integracion continua puede ejecutarse de forma independiente para cada repositorio. Al fusionar un cambio en la rama principal de un microfrontend, el pipeline construye el artefacto, lo sube al CDN y actualiza unicamente la entrada correspondiente del import map. El root config no necesita reconstruirse.

En entornos modernos se utiliza frecuentemente un servicio de import map que permite modificar las URLs de los modulos sin tocar el HTML del contenedor. Esta tecnica facilita rollbacks rapidos: basta con revertir la entrada del mapa a la version anterior del bundle.

Consideraciones de rendimiento y dependencias compartidas

Cargar multiples bundles puede incrementar el tiempo de carga inicial si cada microfrontend incluye su propia copia de React o de otras librerias pesadas. La solucion recomendada es declarar las dependencias compartidas en el import map y configurar cada aplicacion para que no las empaquete.

{
    "imports": {
        "react": "https://cdn.example.com/react.production.min.js",
        "react-dom": "https://cdn.example.com/react-dom.production.min.js",
        "@org/single-spa-demo-nav": "https://cdn.example.com/nav.js"
    }
}

De este modo el navegador descarga una sola instancia de React y la reutiliza en todos los microfrontends. En 2026 la tendencia es combinar esta tecnica con Module Federation o Native Federation cuando se necesita un control mas fino sobre las versiones y la resolucion de conflictos.

La precarga de microfrontends que es probable que el usuario visite a continuacion mejora la percepcion de velocidad. single-spa ofrece APIs para iniciar la descarga de un modulo antes de que su activity function se vuelva verdadera.

Comunicacion entre microfrontends

Aunque el ideal es que cada aplicacion gestione su propio estado, en la practica surgen necesidades de comunicacion. Las opciones mas habituales son eventos personalizados del DOM, un bus de mensajes basado en un utility module o un store compartido cargado como dependencia externa.

Los eventos personalizados mantienen el desacoplamiento:

window.dispatchEvent(
    new CustomEvent("usuario-actualizado", {
        detail: { id: 42, nombre: "Ana" },
    })
);

Cualquier microfrontend puede escuchar el evento y reaccionar en consecuencia. Para datos mas estructurados se puede exponer un utility module que actue como cache compartida de peticiones HTTP, evitando llamadas duplicadas a la misma API.

Pruebas y observabilidad

Las pruebas unitarias de cada microfrontend se ejecutan de forma aislada. Las pruebas de integracion requieren levantar el root config junto con los modulos bajo prueba. Herramientas como Cypress o Playwright permiten simular la navegacion completa y verificar que los ciclos de montaje y desmontaje se comportan como se espera.

La observabilidad transversal es critica. Cada microfrontend debe emitir metricas y traces con un identificador comun de sesion o de solicitud. Plataformas como OpenTelemetry facilitan la correlacion de eventos originados en distintos bundles. Los errores no capturados deben reportarse a un servicio centralizado junto con el nombre de la aplicacion que los produjo.

Comparacion con enfoques alternativos en 2026

Module Federation se ha consolidado como la opcion preferida cuando todos los equipos comparten el mismo framework y el mismo bundler. Ofrece tipado transversal y deduplicacion automatica de dependencias. single-spa conserva su ventaja cuando es necesario componer frameworks distintos o migrar de forma gradual desde un monolito legacy.

La composicion en tiempo de construccion mediante paquetes npm sigue siendo valida para equipos pequenos o para bibliotecas de componentes compartidos. Los iframes proporcionan el maximo aislamiento a costa de una experiencia de usuario menos fluida y un mayor consumo de memoria.

La eleccion debe basarse en el numero de equipos, la diversidad tecnologica y la necesidad real de despliegues independientes. Para organizaciones con menos de tres o cuatro equipos, un monorepo bien estructurado suele ser mas sencillo y eficiente.

Buenas practicas de mantenimiento a largo plazo

Mantener la autonomia requiere disciplina. Cada microfrontend debe versionarse de forma semantica y documentar sus contratos publicos. Los cambios que rompen la compatibilidad deben coordinarse o implementarse detras de feature flags.

El root config debe permanecer lo mas delgado posible. Cualquier logica de negocio o de presentacion que se introduzca en el contenedor crea un nuevo punto de acoplamiento. La autenticacion, el layout global y la telemetria basica son responsabilidades legitimas del contenedor; el resto debe residir en los microfrontends.

La documentacion viva del mapa de aplicaciones, las versiones desplegadas y los owners de cada modulo reduce el tiempo de diagnostico cuando aparece un problema en produccion. Automatizar la generacion de este inventario a partir de los pipelines de CI evita que la informacion quede desactualizada.

Conclusiones

La arquitectura de microfrontends con single-spa permite dividir el frontend en unidades desplegables de forma independiente, preservando al mismo tiempo una experiencia de usuario cohesionada. El root config orquesta el ciclo de vida, los mapas de importacion resuelven las ubicaciones de los modulos y cada equipo conserva autonomia sobre su codigo.

En 2026 el ecosistema ofrece multiples caminos. single-spa sigue siendo una solucion solida cuando se requiere neutralidad de framework o una migracion gradual. Module Federation y Native Federation aportan ventajas adicionales de tipado y comparticion de dependencias cuando el stack es homogeneo. La decision correcta depende del contexto organizativo mas que de la moda tecnica.

Implementar esta arquitectura exige inversion inicial en infraestructura de despliegue, observabilidad y gobierno de dependencias. Cuando esa inversion se realiza con criterio, el resultado es una plataforma frontend capaz de evolucionar al ritmo de multiples equipos sin convertirse en un monolito de coordinacion.