ADVERTENCIA explicar la configuración recomendada de single spa, requiere un blog bastante amplio y, es por ello que te pido que te pongas cómodo y empecemos ya...
El paquete npm single-spa no opina sobre sus herramientas de construcción, proceso de CI o flujo de trabajo de desarrollo local. Sin embargo, para implementar single-spa tendrás que averiguar todas esas cosas (y más).
Para ayudarte a decidir cómo enfocar estos problemas, el equipo central de single-spa ha elaborado una "configuración recomendada" que ofrece un enfoque orientado a resolver los problemas prácticos de los microfrontend.
Resumen
Recomiendan una configuración que utilice módulos ES en el navegador + mapas de importación (o SystemJS para rellenarlos si necesita un mejor soporte en el navegador).
Esta configuración tiene varias ventajas:
- Las bibliotecas comunes son fáciles de gestionar y sólo se descargan una vez. Si estás usando SystemJS, también puedes precargarlas para aumentar la velocidad.
- Compartir código / funciones / variables es tan fácil como importar/exportar, al igual que en una configuración monolítica.
- La carga perezosa de las aplicaciones es fácil, lo que le permite acelerar los tiempos de carga iniciales.
- Cada aplicación (AKA microservicio, AKA módulo ES) puede ser desarrollada y desplegada independientemente. Los equipos pueden trabajar a su propio ritmo, experimentar (dentro de lo razonable, tal y como lo define la organización), realizar el control de calidad y desplegar en sus propios horarios. Esto suele significar también que los ciclos de lanzamiento pueden reducirse a días en lugar de semanas o meses.
- Una gran experiencia para el desarrollador (DX): vaya a su entorno de desarrollo y añada un mapa de importación que apunte la url de la aplicación a su localhost.
- Alternativas qiankun es una alternativa popular a esta configuración recomendada.
- Isomorphic Layout Composer - solución completa para la composición de Micro Frontends en SPA con soporte SSR
- Módulos en el navegador frente a módulos en tiempo de compilación
Un módulo JavaScript en el navegador es cuando las importaciones y exportaciones no son compiladas por su herramienta de construcción, sino que se resuelven dentro del navegador.
Esto es diferente de los módulos en tiempo de compilación, que son suministrados por su nodemodules y compilados antes de que toquen el navegador.
La forma de decirle a webpack y rollup que dejen algunas dependencias sin tocar durante la construcción, para que vengan del navegador, es a través de webpack externals y rollup externals.
Recomendaciones:
- Cada aplicación de un solo espacio debe ser un módulo Javascript dentro del navegador.
- Cada dependencia compartida grande (es decir, las bibliotecas de react, vue, o angular) también debe ser un módulo en el navegador.
- Todo lo demás debería ser un módulo en tiempo de compilación.
Importar mapas
Import Maps (Mapas de Importación)
Los mapas de importación son una especificación del navegador para asignar "especificadores de importación" a una URL. Un especificador de importación es la cadena que indica qué módulo debe cargarse. Ejemplos:
// ./thing.js is the import specifier
import thing from './thing.js';
// react is the import specifier
import React from 'react';
Los especificadores que no son una URL se llaman "especificadores desnudos", como import 'react'.
Ser capaz de asignar un alias a los especificadores desnudos a una URL es crucial para poder utilizar módulos en el navegador, que es la razón por la que existen los mapas de importación.
Los mapas de importación no son compatibles con todos los navegadores. Consulta https://caniuse.com/import-maps para obtener más detalles. Puede utilizar SystemJS o es-module-shims para rellenar el soporte de los mapas de importación.
Module Federation (Federación de módulos)
La Federación de Módulos es una técnica específica de los paquetes web para compartir módulos en tiempo de compilación. Implica que cada microfrontend agrupa todas sus dependencias, incluso las compartidas.
Esto significa que hay múltiples copias de cada dependencia compartida una por microfrontend.
En el navegador, se descargará la primera copia de la dependencia compartida, pero los siguientes microfrontend reutilizarán esa dependencia compartida sin descargar su copia.
Single-spa es una forma de estructurar tus rutas. Module Federation es una técnica de rendimiento. Se complementan bien y pueden usarse juntas.
Con la federación de módulos, deberás elegir cómo desea cargar los propios microfrontend.
Dato relevante: El equipo del núcleo de single-spa recomienda utilizar SystemJS + mapas de importación como cargador de módulos. Como alternativa, puede utilizar variables globales y elementos
SystemJS
SystemJS proporciona un comportamiento similar al del polyfill para los mapas de importación y los módulos en el navegador.
No es un verdadero polyfill de mapas de importación, debido a las limitaciones del lenguaje JavaScript en el polyfilling de la resolución de los especificadores de importación desnudos a las URL.
Dado que SystemJS sólo es polyfill, tendrás que compilar tus aplicaciones en formato System.register en lugar de en formato ESM. Esto permite emular completamente los módulos del navegador en entornos que no soportan módulos o mapas de importación.
Para compilar tu código en formato System.register, establece el output.libraryTarget de webpack en "system", o establece el formato de rollup en "system".
Las dependencias compartidas como React, Vue y Angular, no publican versiones System.register de sus bibliotecas. Como alternativa, SystemJS es capaz de cargarlas a través de la carga global o de los extras AMD y named-exports.
Otro recurso para compartir dependencias es el proyecto self-hosted-shared-dependencies.
Una alternativa a SystemJS que proporciona un comportamiento polyfill para los mapas de importación es es-module-shims. Esto tiene la ventaja de utilizar módulos ES verdaderamente nativos.
Sin embargo, no es el enfoque recomendado por el equipo del núcleo de es-spa para las aplicaciones de producción, ya que requiere un menor rendimiento en el análisis sintáctico del navegador y la modificación de todos sus paquetes.
Lazy loading
La carga perezosa es cuando sólo se descarga el código JavaScript que el usuario necesita para la página actual, en lugar de todo el JavaScript por adelantado. Es una técnica para mejorar el rendimiento de su aplicación disminuyendo el tiempo de renderizado significativo cuando se carga inicialmente la página.
Si utilizas funciones de carga única, ya tiene incorporada la carga perezosa para tus aplicaciones y paquetes. Dado que una aplicación es un "módulo dentro del navegador", esto significa que sólo descarga los módulos dentro del navegador en su mapa de importación cuando los necesita.
A menudo, la carga perezosa basada en rutas que proporcionan las funciones de carga de un solo espacio es todo lo que necesita para garantizar un gran rendimiento. Sin embargo, también es posible realizar la carga perezosa a través de "code splits" con tu bundler (webpack o rollup).
Para la documentación sobre las divisiones de código de webpack, consulte estos documentos. Se recomienda utilizar la importación dinámica (import()) en lugar de múltiples puntos de entrada para las divisiones de código en una aplicación de un solo espacio.
Desarrollo Local
A diferencia de las aplicaciones frontend monolíticas, el desarrollo local con single-spa anima a ejecutar únicamente el microfrontend en el que se está trabajando, mientras se utilizan versiones desplegadas de todos los demás.
Esto es importante porque ejecutar todos los microfronts de single-spa cada vez que se quiere hacer algo es poco manejable y engorroso.
Para lograr el desarrollo local de un solo microfrontend a la vez, podemos personalizar la URL para ese microfrontend dentro del mapa de importación.
Un ejemplo sencillo es el que podemos ver a continuación
{
"imports": {
"@react-mf/navbar": "https://localhost:8080/react-mf-navbar.js",
"@react-mf/planets": "https://react.microfrontends.app/planets/2717466e748e53143474beb6baa38e3e5320edd7/react-mf-planets.js",
"@react-mf/things": "https://react.microfrontends.app/things/7f209a1ed9ac9690835c57a3a8eb59c17114bb1d/react-mf-things.js"
}
}
Existe una herramienta llamada import-map-overrides para personalizar tu mapa de importación a través de una interfaz de usuario en el navegador.
Esta herramienta te permitirá alternar automáticamente uno o más microfronts entre tu localhost y la versión desplegada.
Como alternativa, puedes utilizar el plugin standalone-single-spa-webpack, que te permite desarrollar cada aplicación en modo autónomo.
Otra alternativa es ejecutar siempre la configuración raíz de single-spa localmente, además de los microfronts que estés desarrollando.
El equipo del núcleo de single-spa recomienda el desarrollo en entornos desplegados a través de import-map-overrides, ya que encontramos que es la mejor experiencia para el desarrollador, porque no solo le permite sólo iniciar un proyecto a la vez, sino que también asegura que no hay diferencia entre el entorno local y el entorno desplegado totalmente integrado.
Sin embargo, hay casos en los que ejecutar la configuración raíz localmente o usar el plugin standalone-single-spa-webpack puede ser útil.
Herramientas de construcción
Es muy recomendable utilizar un bundler como webpack, rollup, parceljs, pikapack, entre otros.
Webpack es un estándar de la industria para compilar muchos archivos fuente de JavaScript en uno o más paquetes de JavaScript de producción.
A continuación se presentan algunos consejos para configurar tu bundler para que sea consumible por SystemJS y single-spa.
Ten en cuenta que si estás usando create-single-spa todos estos están configurados para ti.
Te dejo estas instrucciones aquí para no abrumarte con el infierno de la configuración de webpack, sino para ayudarte si decides no usar create-single-spa.
- Establece el objetivo de salida a system. En webpack, esto se hace a través de output.libraryTarget
- Utiliza un único punto de entrada, con importaciones dinámicas para cualquier división de código que quieras realizar. Esto es lo que mejor se ajusta al paradigma de "un proyecto empaquetado = un módulo en el navegador" alentado por el equipo central de single-spa.
- No utilices las opciones de configuración de optimización de webpack, ya que dificultan la carga de los archivos JavaScript de salida como un único módulo JavaScript en el navegador. Hacerlo no hace que tu paquete esté menos optimizado, las importaciones dinámicas son una estrategia viable para lograr paquetes optimizados.
- Sigue la documentación de systemjs para webpack.
- Considera el uso de systemjs-webpack-interop para crear o verificar tu configuración de webpack.
- Utiliza systemjs-webpack-interop para establecer tu ruta pública de webpack "sobre la marcha".
- No establezcas webpack output.library. SystemJS no necesita un nombre, y de hecho no soporta módulos con nombre sin una configuración adicional.
- Considera desactivar el hashing de webpack tanto para los paquetes de entrada como para los de división de código. A menudo es más fácil añadir en un hash de confirmación durante el despliegue de su microfrontend a través de sus variables de entorno CI.
- Configurar webpack-dev-server para que no haga comprobaciones de host. (docs).
- Configurar webpack-dev-server para CORS estableciendo {headers: {'Access-Control-Allow-Origin': '*'}}. (docs)
- Si desarrollas en https, configura webpack-dev-server para HTTPS. También considera confiar en los certificados SSL de localhost.
- Asegúrate de que tus externos de webpack están correctamente configurados para cualquier módulo compartido en el navegador que estés importando.
- Configura output.jsonpFunction para que sea una cadena única para este proyecto. Dado que tendrás varios paquetes de webpack ejecutándose en la misma pestaña del navegador, una colisión de la jsonpFunction podría dar lugar a que los módulos de webpack se mezclen entre los paquetes.
- Establece sockPort, sockPath y sockHost dentro de la configuración de tu devServer.
- Para webpack, establece output.devtoolNamespace con el nombre de tu MFE. Esto ayuda a asignar un espacio de nombres a tus mapas de fuentes para cada MFE.
Módulos de Utilidad
Un "módulo de utilidad" es un módulo JavaScript dentro del navegador que no es una aplicación o parcela única. En otras palabras, su único propósito es exportar funcionalidad para que otros microfronts la importen.
Algunos ejemplos comunes de módulos de utilidad son las guías de estilo, los ayudantes de autenticación y los ayudantes de la API. Estos módulos no necesitan ser registrados con single-spa, pero son importantes para mantener la consistencia entre varias aplicaciones y parcelas de single-spa.
Ejemplo de código en un módulo de utilidad:
// In a repo called "api", you may export functions from the repo's entry file.
// These functions will be available to single-spa application, parcels, and other in-browser modules
// via an import statement.
export function authenticatedFetch(url, init) {
return fetch(url, init).then(r => {
// Maybe do some auth stuff here
return r.json()
})
}
Ejemplo de código en una aplicación de un solo spa que está utilizando el módulo de utilidad:
// Inside of a single-spa application, you can import the functions from the 'api' repo
import React from 'react'
import { authenticatedFetch } from '@org-name/api';
export function Foo(props) {
React.useEffect(() => {
const abortController = new AbortController()
authenticatedFetch(`/api/clients/${props.clientId}`, {signal: abortController.signal})
.then(client => {
console.log(client)
})
return () => {
abortController.abort()
}
}, [props.clientId])
return null
}
Para que los módulos de utilidad funcionen, debes asegurarte de que tus externos de webpack y el mapa de importación están correctamente configurados.
Importaciones cruzadas del microfront
Ejemplo: Exportación de un componente compartido, importación de un componente compartido, y configuración de webpack requerida.
Puedes importar y exportar funciones, componentes, lógica, datos, emisores de eventos y variables de entorno entre tus microfronts que están en diferentes repos de git y paquetes de JavaScript.
Cada microfrontend debe tener un único archivo de entrada que sirve como "interfaz pública" que controla lo que se expone fuera de el.
Para hacer posible la importación de microfondos, configura tu bundler para que los microfronts sean tratados como "externos" (webpack docs / rollup docs).
Marcarlos como externos y asegurate que sean tratados como módulos dentro del navegador en lugar de módulos en tiempo de compilación.
// Inside of the "entry file" for a utility module called @org-name/auth,
// expose your public interface that other microfrontends can access.
// Often this is within the main.js or main.single-spa.js file.
export function userHasAccess(permission) {
return loggedInUser.permissions.some(p => p === permission);
}
import { userHasAccess } from '@org-name/auth'
// Inside of a single-spa application, import and use a util function from a different microfrontend
const showLinkToInvoiceFeature = userHasAccess('invoicing');
// In your webpack config, mark @org-name auth as a webpack external
module.exports = {
externals: ['@org-name/auth'],
// Alternatively, mark *all* org-name packages as externals
// externals: [/^@org-name\/.+/]
}
Dependencias Compartidas
Para el rendimiento, es crucial que tu aplicación web cargue grandes bibliotecas de JavaScript sólo una vez.
El framework que elijas (React, Vue, Angular, etc.) sólo debería cargarse en la página una sola vez.
No es aconsejable hacer que todo sea una dependencia compartida, porque las dependencias compartidas deben actualizarse a la vez para cada microfront que las utilice.
Para las bibliotecas pequeñas, es probablemente aceptable duplicarlas en cada microfront que las utilice.
Por ejemplo, react-router es probablemente lo suficientemente pequeño como para duplicarlo, lo cual es bueno cuando se quiere actualizar el enrutamiento de un microfrontend a la vez, sin embargo, para grandes bibliotecas como react, momentjs, rxjs, entre otros, puedes considerar hacerlas dependencias compartidas.
Hay dos enfoques para compartir dependencias:
- Módulos en el navegador con mapas de importación.
- Módulos en tiempo de compilación con federación de módulos.
Puedes utilizar uno de los dos, o ambos. Actualmente es recomendable sólo el uso de mapas de importación, aunque no se tiene ninguna objeción a la de module federation.
Compartir mapas de importación
Para compartir una dependencia entre microfronts con Mapas de Importación, debes utilizar webpack externals, rollup externals o similares.
Marcar las bibliotecas como externas indica a tu bundler que no utilice la versión en su node modules, sino que espere que la biblioteca exista como un módulo dentro del navegador.
Para que las dependencias compartidas estén disponibles como módulos dentro del navegador, deben estar presentes en tu mapa de importación.
Una buena manera de gestionarlas es crear un repositorio llamado shared-dependencies que tenga un mapa de importación parcial en él.
El proceso de CI para ese repositorio consiste en actualizar tu mapa de importación desplegado. La actualización de las dependencias compartidas se puede lograr haciendo un pull request a ese repositorio.
No todas las bibliotecas publican su código en un formato adecuado para el consumo de SystemJS.
En esos casos, consulta para obtener una versión de SystemJS de esas bibliotecas. Como alternativa, puedes utilizar los extras de SystemJS para soportar los paquetes UMD, que suelen estar disponibles.
Otra opción para encontrar una versión adecuada de una biblioteca para tu mapa de importación es utilizar la CDN de JSPM, que proporciona versiones SystemJS precompiladas de cada paquete en npm.
Consulta para obtener más información. Puedes generar un mapa de importación para tus dependencias compartidas aquí.
Otra opción para alojar dependencias compartidas es self-hosted-shared-dependencies, que genera un directorio de paquetes de terceros que puedes autoalojar en tu servidor / CDN.
Un ejemplo de un repo de dependencias compartidas, junto con un proceso de CI que funciona, se puede encontrar aquí
Compartir Module Federation
En el momento de escribir este artículo, la federación de módulos es nueva y sigue cambiando.
Echa un vistazo a este ejemplo de repo que utiliza systemjs para cargar los microfrontends, pero la federación de módulos para compartir react, react-dom, y react-router.
Despliegue e Integración Continua (CI)
Los microfrontales se construyen y despliegan de forma completamente independiente. Esto significa que el repositorio git, el CI, la construcción y los despliegues ocurren sin pasar por un repositorio centralizado.
Por esta razón, los monorepos no son recomendables para los microfronts.
El CI para monorepos puede ser configurado para construir y desplegar sólo los paquetes que han cambiado, pero a menudo es más complejo. Sin embargo, las plataformas modernas de CI como AWS Amplify y Vercel están empezando a tener soporte integrado para monorepos.
Hay dos pasos para desplegar un microfrontend.
- Subir los paquetes de JavaScript de producción a un servidor web / CDN. Se recomienda el uso de un CDN como AWS S3 + Cloudfront, Google Cloud Storage, Microsoft Azure Storage, Digital Ocean Spaces, entre otros. Debido a su disponibilidad superior, el almacenamiento en caché, y el rendimiento debido a las ubicaciones de borde. Los archivos JavaScript que se suben son completamente estáticos. Se recomienda escribir siempre nuevos archivos en la CDN en lugar de sobrescribirlos.
- Actualiza tu mapa de importación para que apunte al archivo recién desplegado.
La implementación del paso 1 depende de la infraestructura que utilice para su CDN. La CLI de AWS (aws s3 sync), gsutil de Google (gsutil cp), entre otros. son formas sencillas de llevar a cabo esto.
Si prefieres o requieres usar contenedores docker en lugar de un almacenamiento en la nube como S3, consulta https://github.com/single-spa/docker-import-maps-mfe-server
Para la implementación del Paso 2, tienes una opción:
a) Su CI hace una llamada HTTP de curl a una instancia en ejecución de import-map-deployer, que actualiza el mapa de importación de una manera concurrente-segura.
Está opción tiene como ventaja que es seguro para múltiples despliegues simultáneos. Sin una solución segura para la concurrencia, puede haber varios procesos que descarguen y vuelvan a cargar el mapa de importación al mismo tiempo, lo que podría dar lugar a una condición de carrera en la que un proceso de CI piense que ha actualizado con éxito el mapa de importación cuando en realidad el otro proceso de CI escribió el mapa de importación más tarde, habiendo basado sus cambios en una versión antigua del mapa de importación.
b) Tu corredor CI baja el mapa de importación, lo modifica, y lo vuelve a subir.
Su ventaja es que no requiere la ejecución del import-map-deployer en su entorno de producción. En última instancia, debe elegir la opción que tenga sentido para su organización.
Otra opción para desplegar y asegurarte de que se utilizan los últimos archivos javascript es hacer uso de la redirección (código de estado HTTP 302).
El mapa de importación simple utiliza la url sin hash del archivo javascript, por ejemplo: dist/app.js. Entonces, cuando las solicitudes de este archivo llegan al servidor, se redirige al archivo desplegado real, por ejemplo, dist/app.123abc.js y esto se sirve al cliente.
De esta manera el mapa de importación nunca tiene que ser actualizado y el microfrontend puede ser desplegado por separado.
Aplicaciones versus Parcels versus Módulos de Utilidad
Single-spa dispone de diferentes categorías de microfronts. Depende de ti dónde y cómo utilizar cada una de ellas. Sin embargo, el equipo central de Single-spa recomienda lo siguiente:
Muchas aplicaciones single-spa basadas en rutas, muy pocos paquetes single-spa.
Preferir la división de los microfronts por rutas, en lugar de por componentes dentro de una ruta. Esto significa preferir las aplicaciones single-spa a las parcelas single-spa siempre que sea posible.
El motivo es que las transiciones entre rutas suelen implicar la destrucción y recreación de la mayor parte del estado de la interfaz de usuario, lo que significa que tus aplicaciones single-spa en diferentes rutas no necesitan compartir nunca el estado de la interfaz de usuario.
Mueve los menús de navegación fijos a tus propias aplicaciones single-spa. Implementa tus funciones de actividad para que estén activas por defecto, y sólo se desmonten para la página de inicio de sesión.
Crea módulos de utilidad para tu biblioteca de componentes principales / guía de estilo, para la autenticación compartida / código de autorización, y para el manejo global de errores.
Si sólo estás usando un framework, opta por preferir los componentes de framework (es decir, componentes de React, Vue y Angular) en lugar de paquetes de un solo espacio.
Esto se debe a que los componentes del framework interoperan más fácilmente entre sí que cuando hay una capa intermedia de paquetes single-spa.
Puedes importar componentes entre aplicaciones single-spa Sólo deberías crear un paquete single-spa si necesitas que funcione con múltiples frameworks.
Comunicación entre aplicaciones
Una buena arquitectura es aquella en la que los microfronts están desacoplados y no necesitan comunicarse con frecuencia.
Seguir las directrices anteriores sobre las aplicaciones frente a los paquetes le ayuda a mantener tus microfronts desacoplados.
Las aplicaciones de un solo paquete basadas en rutas requieren intrínsecamente menos comunicación entre aplicaciones.
Hay tres cosas que los microfronts pueden necesitar compartir / comunicar:
- Funciones, componentes, lógica y variables de entorno.
- Datos de la API
- Estado de la UI
Funciones, componentes, lógica y variables de entorno.
Es recomendable el uso de importaciones cruzadas de microfronts para compartir funciones, componentes, lógica y variables de entorno.
API DATA
A menudo no es necesario compartir los datos de la API entre los microfronts, ya que cada aplicación single-spa controla diferentes rutas y las diferentes rutas suelen tener datos diferentes. Sin embargo, en ocasiones sí es necesario compartir los datos de la API entre microfronts.
Una caché JavaScript en memoria de los objetos de la API es una solución utilizada por varias empresas para resolver esto.
Para los usuarios de React, esto es similar a la obtención de datos con Suspense, donde la lógica de obtención de rutas se separa del código del componente que utiliza los datos.
// Inside of your api utility module, you can lazily fetch data either when another microfrontend calls your exported
// functions, or eagerly fetch it when the route changes.
let loggedInUserPromise = fetch('...').then(r => {
if (r.ok) {
return r.json()
} else {
throw Error(`Error getting user, server responded with HTTP ${r.status}`)
}
})
export function getLoggedInUser() {
return loggedInUserPromise;
}
import { getLoggedInUser } from '@org-name/api';
// Inside of app1, you can import something from an "api" utility module
getLoggedInUser().then(user => {
console.log('user', user);
});
Estado de Interfaz de Usuarios
Si dos microfronts se pasan frecuentemente el estado entre ellos, considera la posibilidad de fusionarlos.
Las desventajas de los microfronts aumentan cuando tus microfronts no son módulos aislados.
El estado de la interfaz de usuario, como "¿está abierto el modal?", "¿cuál es el valor actual de esa entrada?", entre otros., en gran medida no necesita ser compartido entre los microfronts.
Si te encuentras con la necesidad de compartir constantemente el estado de la interfaz de usuario, es probable que tus microfronts estén más acoplados de lo que deberían. Considera la posibilidad de fusionarlos en un único microfrontend.
En las raras circunstancias en las que se necesita compartir el estado de la interfaz de usuario entre aplicaciones de un solo espacio, se puede utilizar un emisor de eventos para hacerlo.
A continuación se muestran algunos ejemplos de emisores de eventos que pueden ayudarte.
- Observables / Sujetos (rxjs) - un microfrontend emite nuevos valores a un flujo que puede ser consumido por cualquier otro microfron. Exporta el observable a todos los microfrontales desde su módulo en el navegador, para que otros puedan importarlo.
- CustomEvents - los navegadores tienen un sistema incorporado de emisión de eventos que le permite disparar eventos personalizados. Consulte esta documentación para obtener más información. Disparar los eventos con window.dispatchEvent te permite suscribirte en cualquier otro microfrontend con window.addEventListener.
- Cualquier otro sistema emisor de eventos pub/sub.
Gestión de Estados
El equipo del núcleo de single-spa desaconseja el uso de redux, mobx y otras bibliotecas de gestión de estados globales.
Sin embargo, si deseas utilizar una biblioteca de gestión de estados, es recomendable que mantengas las herramientas de gestión de estados específica para un único repositorio / microfrontend en lugar de un único almacén para todos tus microfrontends.
La razón es que los microfronts no son realmente desacoplados o agnósticos si todos deben usar un almacén global.
No puedes desplegar independientemente un microfrontend si depende del estado del almacén global para tener una forma específica o tener acciones específicas disparadas por otros microfrontends para hacerlo tendrías que pensar muy bien si tus cambios en el almacén global son compatibles hacia atrás y hacia adelante con todos los otros.
Además, gestionar el estado global durante las transiciones de las rutas ya es bastante difícil sin la complejidad de que varios microfrontales contribuyan al estado global y lo consuman.
En lugar de un almacén global, el equipo del núcleo de single-spa recomienda utilizar el estado de los componentes locales para sus componentes, o un almacén para cada uno de sus microfronts.