Saltar a contenido

Microfrontends con CRA

Deprecated

CRA se encuentra deprecado y ya no es posible crear proyectos utilizando estos templates. La documentación queda como referencia para todas aquellos proyectos que todavía no se han migrado.

Se tienen dos templates de CRA para trabajar con Microfrontend, para módulo y shell, que utilizan Module Federation para generar las configuraciones necesarias que permiten convertir una aplicación en un MF.

Los templates de MF estan basados en el template base de CRA. Se puede visualizar el Workshop de Frontend realizado, para ver mejor como está conformado y su funcionamiendo.

Module Federation

El archivo moduleFederation.config.js es una parte esencial de la configuración de un microfrontend basado en Module Federation. Proporciona información crucial para la correcta integración y comunicación entre diferentes microfrontends en una arquitectura distribuida.

Propiedades

  1. name: El nombre único del microfrontend que se utilizará para identificarlo dentro del sistema.

  2. library: Define cómo se expone el microfrontend como un módulo, generalmente utilizando el formato "var", "amd", "commonjs" o "umd".

  3. filename: El nombre del archivo generado para el microfrontend. Se puede personalizar para facilitar la caché y el versionamiento.

  4. remotes: Una lista de microfrontends externos a los que este microfrontend desea acceder. Aquí se definen las dependencias y módulos remotos.

  5. expose: Los módulos locales que este microfrontend está dispuesto a compartir con otros microfrontends.

  6. shared: Los módulos compartidos que pueden ser utilizados por varios microfrontends. Esto permite reducir el tamaño del paquete y mejorar la eficiencia de la aplicación.

En conjunto, el moduleFederation.config.js es un archivo crucial para establecer la interoperabilidad entre los diferentes microfrontends en una arquitectura de Module Federation, permitiendo que los microfrontends se comuniquen y compartan recursos de manera eficiente y organizada.

ModuleFederation

Template Shell

El template nos provee toda la configuracion inicial para poder levantar un shell sin problemas ejecutando npm start donde ya tiene integrado su login para comenzar a trabajar con b2c, tambien unos ejemplos para tener como referencias como las rutas (como generarlas), pages, ejemplos de domain y services para ayudar a la implementacion.

npm start

login

En cuanto a la arquitectura de carpetas dentro de src:

name descripción
adapters ejemplo de como adaptar un objeto o transformarlo a una necesidad
app ejemplo de como llamar a un metodo configurado en el services
components alerts - idTokenClaims - SecureWrapper
domain estructuras de objetos
hooks van nuestras funciones Hook customizadas con un ejemplo
layout pagina presentacional inicial
pages declaracion de paginas de la app con sus nombres y estilos
routes componente donde se declaran las rutas con su path y se configura el path con el que se consumira el module
services donde se declaran los endpoint a consumir , un ejemplo de datos locales
store ejemplo de como gestionar el estado global compartido entre los diferentes componentes del microfrontend. Es una estructura centralizada que permite acceder y modificar los datos desde cualquier parte del microfrontend de manera predecible y eficiente

Las configuraciones para conectar un shell y un módulo, se deberían hacer utilizando las utilidades de la librería @architecture-it/microfrontend-utils, en cuya documentación se especifican las configuraciones a realizar.

REACT_APP_MFE_REMOTE=remote@http://localhost:3001/remoteEntry.js

env

Info

En los environments del shell Luego de REACT_APP_MFE_{nombre del module} (nombre del modulo) aqui especifica que se conectara con el microfrontend subido al puerto 3001, lo que quiere decir que para acceder y probar su convivencia necesitamos tener levantado ambos proyectos y basandonos en la configuracion que mencionamos en las rutas para acceder a las rutas del module debemos agregar el path /module para acceder al index del microfront consumido (module) o al path del mismo desde nuestro shell

Template Módulo

Al igual que para el shell, el template del módulo tiene todas las configuraciones básicas para levantar un proyecto y conectarlo con otros MF.

Se debe configurar Module Federation para discriminar el nombre identificatorio del módulo (el que luego también va a utilizar el shell para conectarse) y para exponer todas las secciones de nuestra aplicación que se quieran poder consumir desde otros microfrontends, utilizando la propiedad expose.

ModuleFederationModule

Ejemplo nombre modulo

Warning

  • Recordar que para probar la conexion entre ambos luego de dichas configuraciones es necesario que ambos proyectos esten levantados.

  • Para el uso de librerias compartidas entre dos MFEs donde el shell especifica la version para compartir dicha libreria, por el momento optamos por no compartir ninguna libreria en el ecosistema. Se levanto una issue para analizar el problema y su configuracion ya que la misma en el moduleFederation no reacciona como deberia. Se deja la imagen como ejemplo: Ejemplo sin shared

FAQ

Los estilos entre los MicroFrontends se pisan
  1. Instalar la librería microfrontend-utils utilizando el manejador de paquetes de tu proyecto npm/pnpm:

    pnpm i @architecture-it/microfront-utils
    
  2. Agregar la función addMicrofrontCssIdenName dentro del export de override enviando los parámetros config y env provenientes de la configuración de webpack antes de retornar config.

  3. Aplicar el mismo procedimiento para los módulos.

Ejemplo de implementación en un proyecto legacy:

const { addMicrofrontCssIdenName } = require("@architecture-it/microfront-utils/overwrite");
const webpack = require("webpack");

/**
 *
 * @param {import("webpack").Configuration} config
 * @param {*} env
 * @returns {import("webpack").Configuration}
 */
module.exports = function override(config, _env) {
  const fallback = config.resolve.fallback || {};

  Object.assign(fallback, {
    crypto: require.resolve("crypto-browserify"),
    stream: require.resolve("stream-browserify"),
    assert: require.resolve("assert"),
    http: require.resolve("stream-http"),
    https: require.resolve("https-browserify"),
    os: require.resolve("os-browserify"),
    url: require.resolve("url"),
    util: require.resolve("util/"),
  });
  config.resolve.fallback = fallback;

  config.plugins = (config.plugins || []).concat([
    new webpack.ProvidePlugin({
      process: "process/browser",
      Buffer: ["buffer", "Buffer"],
    }),
  ]);

  config.ignoreWarnings = [/Failed to parse source map/];

  // Agrega la función para manejar los prefijos de CSS
  addMicrofrontCssIdenName(config, _env);

  return config;
};