Gestionar Estado Global con Librerías como Redux

Lectura
25 min~4 min lectura

Concepto clave

En arquitecturas de micro-frontends, gestionar el estado global es como coordinar varios departamentos en una gran empresa. Cada micro-frontend (equipo) trabaja de forma independiente, pero necesita compartir información crítica como datos de usuario, preferencias o estado de la aplicacion. Redux emerge como una solucion robusta para este desafio, proporcionando un almacen centralizado y predecible que puede ser accedido por multiples aplicaciones federadas.

Imagina una cadena de hoteles donde cada propiedad (micro-frontend) tiene su propia gestion, pero todas comparten un sistema central de reservas (estado global). Redux actua como ese sistema central: mantiene una unica fuente de verdad, define reglas claras para actualizaciones (a traves de acciones y reducers), y notifica a todas las propiedades cuando hay cambios relevantes. Esto evita que un micro-frontend modifique datos que otro esta usando, previniendo conflictos y comportamientos inesperados.

Como funciona en la practica

Implementar Redux en micro-frontends con Module Federation requiere un enfoque estratificado. Primero, defines un store de Redux en un modulo remoto (host) que sera consumido por los micro-frontends (remotes). Este store debe exponerse via Module Federation, permitiendo que otros bundles lo importen como una dependencia compartida.

Paso a paso: 1) Crea un proyecto host que configure el store de Redux con sus reducers y middlewares. 2) En la configuracion de Webpack, expone el store mediante exposes en Module Federation. 3) En los proyectos remotes, configura remotes para importar el store del host. 4) Usa Provider de React-Redux en el host para envolver la aplicacion, y en los remotes, conecta los componentes usando hooks como useSelector y useDispatch. Esto asegura que todos los micro-frontends accedan al mismo estado, sincronizando datos como autenticacion o temas visuales.

Codigo en accion

Configuracion del store en el host (proyecto principal):

// host/src/store.js
import { createStore, combineReducers } from 'redux';
import userReducer from './reducers/userReducer';
import themeReducer from './reducers/themeReducer';

const rootReducer = combineReducers({
  user: userReducer,
  theme: themeReducer
});

const store = createStore(rootReducer);
export default store;

Exposicion en Webpack config del host:

// host/webpack.config.js
module.exports = {
  // ... otras configuraciones
  plugins: [
    new ModuleFederationPlugin({
      name: 'host',
      filename: 'remoteEntry.js',
      exposes: {
        './store': './src/store'
      },
      shared: { 'react': { singleton: true }, 'react-dom': { singleton: true } }
    })
  ]
};

Uso en un micro-frontend remote:

// remote/src/App.js
import React from 'react';
import { Provider } from 'react-redux';
import store from 'host/store'; // Importacion federada
import UserComponent from './UserComponent';

function App() {
  return (
    <Provider store={store}>
      <UserComponent />
    </Provider>
  );
}
export default App;

Errores comunes

  • No compartir dependencias de Redux: Si react-redux no se comparte como singleton en Module Federation, puede causar multiples instancias y errores de contexto. Solucion: Asegurate de incluir 'react-redux': { singleton: true } en la configuracion shared.
  • Estado inconsistente entre recargas: Al recargar un micro-frontend, el store podria reiniciarse si no esta bien persistido. Solucion: Usa middlewares como redux-persist para guardar el estado en localStorage o sessionStorage.
  • Acciones no serializables: Enviar funciones o Promises en acciones de Redux puede romper la predictibilidad. Solucion: Manten las acciones como objetos planos con tipos y datos simples, usando thunks o sagas para logica asincrona.
  • Sobrecarga del store global: Incluir todo el estado en el store compartido puede ralentizar la aplicacion. Solucion: Divide el estado en global (compartido) y local (especifico de cada micro-frontend), usando Redux solo para lo esencial.

Checklist de dominio

  1. Configurar un store de Redux en un host y exponerlo via Module Federation.
  2. Importar y usar el store en al menos dos micro-frontends remotes.
  3. Compartir dependencias criticas como react-redux como singletons.
  4. Implementar acciones y reducers que manejen datos compartidos, como usuario o tema.
  5. Usar hooks de React-Redux (useSelector, useDispatch) en componentes remotes.
  6. Probar la sincronizacion del estado al realizar cambios desde diferentes micro-frontends.
  7. Optimizar el rendimiento evitando rerenders innecesarios con selectores memorizados.

Integrar Redux en una arquitectura de micro-frontends con Module Federation

En este ejercicio, implementaras un estado global compartido usando Redux entre un host y dos micro-frontends. Sigue estos pasos:

  1. Crea un proyecto host con Webpack y Module Federation. Configura un store de Redux que gestione un estado simple, como un contador y un nombre de usuario.
  2. Expone el store desde el host usando exposes en la configuracion de Module Federation. Asegurate de compartir react-redux como singleton.
  3. Crea dos proyectos remotes (micro-frontends) que importen el store del host. En cada uno, desarrolla un componente que muestre y modifique el estado compartido (e.g., incrementar contador, actualizar usuario).
  4. Conecta los componentes a Redux usando useSelector para leer el estado y useDispatch para enviar acciones.
  5. Ejecuta los proyectos y verifica que los cambios en un micro-frontend se reflejen inmediatamente en el otro, demostrando el estado global sincronizado.
Pistas
  • Usa createStore de Redux en el host y combina reducers para manejar multiples slices de estado.
  • En la configuracion de Webpack, define shared: { 'react-redux': { singleton: true } } para evitar conflictos.
  • Prueba con acciones simples al principio, como incrementar un numero, antes de agregar logica compleja.

Evalua tu comprension

Completa el quiz interactivo de arriba para ganar XP.