Rutas entre microfrontends: dueños de rutas, deep links y contrato de navegación
La URL es lo único que cada microfrontend comparte con todos los demás. Tener reglas claras sobre quién es dueño de cada parte evita la mayoría de los problemas de integración antes de que aparezcan.
Dueños de las rutas
La regla básica es un prefijo por remoto. El host es dueño del primer segmento de la URL y decide a qué remoto pertenece. El remoto es dueño de todo lo que viene después.
| URL | Dueño |
|---|---|
/ y /login | Host |
/billing y todo lo que cuelga | Remoto de facturación |
/catalog y todo lo que cuelga | Remoto de catálogo |
| Cualquier primer segmento desconocido | Host (página de no encontrado) |
Dos remotos nunca comparten un prefijo. Si una pantalla parece pertenecer a dos áreas, elige un dueño y deja que la otra área enlace hacia ella.
Cómo se ve en Angular con federation
El host declara una ruta lazy por remoto. El remoto exporta sus rutas hijas y nunca menciona su propio prefijo.
// host
export const routes: Routes = [
{ path: '', component: HomeComponent },
{
path: 'billing',
loadChildren: () =>
loadRemoteModule('billing', './routes')
.then(m => m.BILLING_ROUTES)
},
{ path: '**', component: NotFoundComponent }
];
// remoto billing
export const BILLING_ROUTES: Routes = [
{ path: '', component: InvoiceListComponent },
{ path: 'invoices/:id', component: InvoiceDetailComponent }
];
Como las rutas del remoto son relativas, el host puede montarlo bajo otro prefijo sin ningún cambio en el remoto.
Lazy loading
Un remoto se descarga la primera vez que se visita su prefijo. Hasta entonces no le cuesta nada al usuario.
Hay dos refinamientos que vale la pena considerar:
- Precarga. Cuando la primera pantalla queda en reposo, el host puede precargar el remoto que el usuario probablemente abrirá después. Mantén la lista corta. Precargar todo elimina el beneficio del lazy loading.
- Estado de carga. La primera visita a un remoto incluye un viaje de red. Muestra un skeleton o un indicador de progreso en el área de contenido, y mantén interactivos el encabezado y el menú.
El efecto sobre los tiempos de carga se discute en Rendimiento de microfrontends.
Deep links
Toda pantalla debe poder abrirse desde un arranque en frío. Un usuario abre /billing/invoices/123 desde un correo, en una pestaña nueva. Tiene que pasar esto:
- El servidor devuelve el
index.htmldel host para cualquier ruta. Es el fallback habitual de una single-page application, y debe cubrir los prefijos de los remotos. - El host arranca y restaura la sesión.
- El router del host reconoce
billingy carga el remoto. - Las rutas del remoto reconocen
invoices/123y la pantalla carga sus propios datos.
Las formas habituales en que esto se rompe:
- Una pantalla supone estado dejado por una pantalla anterior, como un cliente seleccionado en memoria. En un arranque en frío ese estado no existe. Cada pantalla debe poder cargar lo que necesita a partir de la URL.
- Un guard del remoto corre antes de que el host haya restaurado la sesión, y redirige al login en un ciclo.
- El remoto carga sus recursos con URLs relativas, que se resuelven contra la dirección del host en lugar de la del remoto.
- La regla de fallback del servidor cubre
/pero no las rutas anidadas.
Agrega a la suite de integración una prueba de deep link por remoto: abrir una URL interna en una sesión nueva del navegador y verificar que aparece la pantalla correcta. Detecta los cuatro problemas anteriores.
El contrato de navegación
Los equipos deberían acordar estas reglas y dejarlas por escrito.
- La navegación entre áreas usa solo URLs. Facturación enlaza a
/customers/42. No importa un componente ni una constante de rutas del remoto de clientes. - Las URLs públicas son una API. Cada remoto lista las URLs a las que otros pueden enlazar. Esas se mantienen estables o reciben redirecciones. Las URLs internas pueden cambiar libremente.
- La navegación pasa por el router. Asignar
location.hrefrecarga todo el host y pierde el estado en memoria. - El estado que se puede compartir va en la URL. Filtros, pestañas y paginación como query params sobreviven a una recarga y se le pueden enviar a un colega.
- Cada lado maneja sus rutas desconocidas. El host muestra una página de no encontrado para prefijos desconocidos. Cada remoto hace lo mismo dentro de su prefijo.
Hay más formas de intercambiar información entre remotos en Comunicación entre microfrontends.
Cuando los remotos tienen su propio router
Con single-spa, o con remotos envueltos como web components, cada remoto corre su propia instancia de router. Varios routers observan entonces la misma URL. Aplican tres reglas adicionales:
- Cada router maneja solo su prefijo e ignora todo lo demás.
- Toda la navegación pasa por la History API del navegador, para que todos los routers se enteren de los cambios.
- Un remoto que se está desmontando deja de reaccionar a los cambios de URL.
Este modelo se compara en single-spa vs Module Federation.
Checklist
- ¿Cada remoto tiene exactamente un prefijo, y la lista está escrita?
- ¿Los remotos usan solo rutas relativas internamente?
- ¿Un deep link a una pantalla interna funciona en una sesión nueva?
- ¿Hay una lista publicada de URLs públicas por remoto?
- ¿Hay alguna asignación a
location.hrefpara navegación interna? Reemplázala. - ¿Las rutas desconocidas muestran una página útil en los dos niveles?
Más en esta sección
- Cómo compartir login y sesión entre microfrontends
- Cómo se comunican los microfrontends y qué evitar
- Dependencias compartidas y versiones en microfrontends
- Una sola apariencia entre microfrontends: tokens, componentes y aislamiento de estilos
¿Planeas una migración o una plataforma de microfrontends?
En una llamada de 20 minutos me cuentas tu situación y te digo cómo la abordaría. Si todavía no vale la pena, también te lo digo.
Escríbeme por LinkedIn