La arquitectura web se mueve rápido: los microservicios desde el lado del servidor han sido un gran avance para hacer las aplicaciones web más granulares y modulares en lugar de mantener un “monolito”.
1. Evolución de la arquitectura micro-frontend
Desde el lado del cliente (dominado por JavaScript) ha habido también muchos avances para dividir aquel monolito en aplicaciones pequeñas y más fáciles de mantener. Este concepto llega a ser crítico especialmente cuando nos enfrentamos a una aplicación de grandes magnitudes, en la que la complejidad y el mantenimiento pueden llegar a ser un problema. La pregunta es sencilla: ¿no podría simplemente dividir mi aplicación en unidades más pequeñas? Y la respuesta, afirmativa: Sí puedes, con micro-frontend y Module Federation.
Esta idea descansa en que si el backend ha podido modularizar su arquitectura en microservices, el frontend puede hacer lo mismo y dividir el monolito “frontend” en sub-aplicaciones.
1.1 Problemas a resolver
La arquitectura micro-frontend nace para dar solución a un problema muy recurrente en cualquier aplicación: cuanto más crece una aplicación, más difícil y costoso es su mantenimiento. El hecho de tener a varios equipos trabajando en una misma aplicación indivisible puede llegar a ser un trabajo difícil de coordinar. Es lo que llamamos “The Frontend Monolith”.
Para romper el monolito debemos pensar en una aplicación web como una composición de containers/funcionalidades que, juntas, forman la aplicación entera. Estas “features” en lugar de formar parte del chunk “main.js” formarán parte de un chunk aparte, por ejemplo “chunk3.js”.
La aplicación será luego la encargada de servir diferentes aplicaciones o “chunks” , según lo demande el usuario, su navegación y comportamiento.
Siguiendo un enfoque parecido al método de orquestación de contenedores, podemos implementar varias aplicaciones en una sola aplicación contenedor que incluirá la lógica de cómo y cuándo mostrar nuestras aplicaciones frontend.
Podemos dividir nuestra aplicación en:
- Container: Orquestador del resto de aplicaciones.
- MFE1: Aplicación n.1
- MFE2: Aplicación n.2
¿Cómo conseguirlo?
Fácil, conWebpack5 y su funcionalidad Module Federation: https://webpack.js.org/concepts/module-federation/
1.2 Pros/contras de la arquitectura micro-frontend
Pero cambiar algo que lleva funcionando ya mucho tiempo puede generar ciertas resistencias. Por este motivo, es importante analizar en detalle los pros y los contras del micro-frontend
Ventajas:
- Desarrollo más rápido, pues los equipos pueden trabajar independientemente, en vez de estar trabajando en un proyecto de gran envergadura.
- Mayor escalabilidad (divide y vencerás).
- Al ser divisiones unos de otros, los repos acaban siendo más pequeños y manejables.
- ¡Puedes mezclar distintos frameworks en la misma aplicación! Puedes usar Angular para una parte de la app en la que es más recomendable y React, en otra.
- Independencia en el despliegue: el deployment en una aplicación no afectará al resto de la aplicación.
- El testing puede resultar más fácil al estar probando diferentes “features”.
Desventajas:
- La configuración del CI/CD y el deployment involucrará trabajo y conocimiento adicional y en cada aplicación será diferente.
- Para equipos pequeños probablemente no merezca la pena esta implementación.
- Se requiere un esfuerzo extra para que los diferentes equipos trabajen de forma coordinada y con las mismas reglas.
- Testear la aplicación como una pieza entera puede ser complicado.
Muéstrame el código
Lo primero es crear una serie de carpetas:
Dentro de cada carpeta necesitamos:
- Carpeta /src/ Aquí introduciremos nuestra app.
- Carpeta /public/ Carpeta para index.html para inyectar desde React
- Archivo webpack.config.js Configuración Webpack
- Archivo package.json
Después en nuestro contenedor necesitamos un anchor donde nuestras aplicaciones de React se van a renderizar.
Pero la magia ocurre realmente en el archivo webpack.config.js, pues, hasta ahora, ningún contenedor o aplicación conoce la existencia de lo que le rodea. Tenemos que editar el orchestrator y las aplicaciones MFE de una manera ligeramente distinta.
Respecto al contenedor, necesitamos hacerle consciente de que tendrá unos “remotes” que va a tener accesibles:
Debemos importar y agregar el resto de aplicaciones como “remotes” de nuestra aplicación utilizando el ModuleFederationPlugin de Webpack en nuestra configuración de Webpack. Esto nos permitirá que a la hora de importarlo a nuestra aplicación Webpack sepa dónde debe buscarlo.
Es muy importante también señalar explícitamente qué React y React DOM estarán compartidos y serán singletons.