paint-brush
Tomando un viaje hacia la migración de micro-frontend - Parte 1: Diseñopor@isharafeev
1,323 lecturas
1,323 lecturas

Tomando un viaje hacia la migración de micro-frontend - Parte 1: Diseño

por Ildar Sharafeev13m2023/07/12
Read on Terminal Reader

Demasiado Largo; Para Leer

Migrar a una arquitectura de micro-frontend requirió una inversión significativa en términos de estructura organizacional y base operativa. Sería mejor comenzar con una arquitectura monolítica distribuida que aproveche la carga diferida (importaciones dinámicas). Habría una necesidad esencial de dividir la base de código en diferentes áreas de propiedad controladas por diferentes equipos.
featured image - Tomando un viaje hacia la migración de micro-frontend - Parte 1: Diseño
Ildar Sharafeev HackerNoon profile picture

En el acelerado mundo digital actual, donde la agilidad y la escalabilidad son cruciales, las empresas buscan constantemente formas de mejorar el rendimiento y la capacidad de mantenimiento de sus aplicaciones web.


Un enfoque popular para lograr estos objetivos es migrar de una arquitectura monolítica a una distribuida (o micro-frontend). Esta serie de artículos, "Viaje de migración de micro-frontend", comparte mi experiencia personal al realizar una migración de este tipo durante mi tiempo en AWS.


DESCARGO DE RESPONSABILIDAD : antes de comenzar, es importante tener en cuenta que, si bien este artículo comparte mi experiencia personal, no puedo divulgar ningún detalle interno o de propiedad de herramientas, tecnologías o procesos específicos en AWS ni en ninguna otra organización.


Me comprometo a respetar las obligaciones legales y garantizar que este artículo se centre únicamente en los conceptos y estrategias generales involucrados en el viaje de migración de micro-frontend.


El propósito es brindar conocimientos y lecciones aprendidas que puedan aplicarse en un contexto más amplio, sin divulgar ninguna información confidencial.

Motivación para la migración

Aprendí sobre micro-frontends (supongo que muchos de ustedes) del artículo en el blog de Martin Fowler. Presentó diferentes formas de componer la arquitectura de micro-frontend de una manera independiente del marco.


A medida que profundizaba en el tema, me di cuenta de que nuestra arquitectura monolítica existente se estaba convirtiendo en un cuello de botella importante para la productividad de nuestro equipo y obstaculizaba el rendimiento general de nuestra aplicación.


Uno de los factores clave que me empujó a considerar una migración fue el aumento del tamaño del paquete de nuestra aplicación.


Después de realizar un análisis exhaustivo del paquete en el verano de 2020, descubrí que desde su lanzamiento inicial a principios de 2019, el tamaño del paquete (comprimido con gzip) había aumentado de 450 KB a 800 KB (son casi 4 MB analizados), casi el doble del tamaño original.


Teniendo en cuenta el éxito de nuestro servicio y pronosticando su crecimiento continuo, estaba claro que esta tendencia persistiría, lo que afectaría aún más el rendimiento y la mantenibilidad de nuestra aplicación.


Si bien estaba entusiasmado con el concepto de micro-frontends, también reconocí que aún no estábamos listos para adoptarlos debido a los desafíos específicos que enfrentamos:


  1. Estructura organizativa pequeña: en el momento de mi análisis, nuestra organización era relativamente pequeña y yo era el único ingeniero frontend a tiempo completo del equipo. Migrar a una arquitectura de micro-frontend requirió una inversión significativa en términos de estructura organizacional y base operativa.


    Era crucial tener una estructura madura que pudiera manejar de manera efectiva la arquitectura distribuida y reflejar las dependencias entre los diferentes componentes de la interfaz.


  2. Dominio comercial limitado: aunque las micro-frontends se pueden dividir en función de contextos limitados y capacidades comerciales (obtenga más información en la publicación " Diseño basado en dominios en la arquitectura de micro-frontend" ), nuestro dominio comercial principal no era lo suficientemente extenso como para justificar un desacoplamiento completo en Múltiples micro-frontends. Sin embargo, había límites visibles dentro de la aplicación que tenían sentido para tallar y hacer la transición a una arquitectura distribuida.


Teniendo en cuenta estos factores, me di cuenta de que era necesario un enfoque gradual. En lugar de una migración completa a micro-frontends, mi objetivo era identificar áreas específicas dentro de nuestra aplicación que podrían beneficiarse de una arquitectura distribuida.


Esto nos permitiría abordar los problemas de rendimiento y escalabilidad sin interrumpir la estructura organizativa general ni comprometer la integridad de nuestro dominio empresarial. También nos daría algo de tiempo para hacer crecer el equipo y observar las direcciones comerciales.


Tenga en cuenta que si desea abordar el problema de rendimiento de la aplicación (tamaño del paquete) solo mediante el uso de la arquitectura mciro-frontend, puede que no sea la mejor idea. Sería mejor comenzar con una arquitectura monolítica distribuida que aproveche la carga diferida (importaciones dinámicas).


Además, creo que manejaría los problemas de tamaño del paquete con más gracia que la arquitectura de micro-frontend considerando que es muy probable que la arquitectura de micro-frontend tenga algún código compartido que no se separaría en partes del proveedor, y estaría integrado en el paquete de la aplicación ( esa es una de las desventajas de dicha arquitectura distribuida: debe tener un equilibrio entre qué compartir, cuándo y cómo).


Sin embargo, la arquitectura monolítica distribuida no escalará tan bien como la micro-frontend. Cuando su organización crece rápidamente, es probable que su equipo también crezca al mismo ritmo.


Habría una necesidad esencial de dividir el código base en diferentes áreas de propiedad controladas por diferentes equipos.


Y cada equipo deberá tener sus propios ciclos de lanzamiento que sean independientes de los demás, cada equipo apreciará si su base de código se enfoca exclusivamente en su dominio y compilará rápidamente (aislamiento de código -> mejor mantenibilidad/menos código para mantener y construir -> mejor capacidad de prueba/menos pruebas para mantener y ejecutar).

El comienzo

Para obtener el apoyo del liderazgo, elaboré un documento de visión técnica persuasivo que abarcaba un análisis de rendimiento integral, incluidas las métricas vitales de la web, y describía las diversas fases de la migración hacia interfaces distribuidas.


Una de las fases intermedias de esta migración fue establecer una arquitectura monolítica distribuida, en la que varios módulos/widgets podrían entregarse de forma asíncrona a través de técnicas de carga diferida mientras se aprovechaba la infraestructura compartida, como un depósito S3 y CDN, entre el servicio principal y los widgets. .


Como describí en mi artículo anterior, la idea principal de este tipo de documento es describir el futuro como te gustaría que fuera una vez que se hayan logrado los objetivos y se hayan resuelto los problemas más importantes. ¡No se trata del plan de ejecución!


Casi 1 año después, finalmente había llegado el momento de poner en práctica mi plan de migración de micro-frontend. Con la inminente expansión a un nuevo dominio y un equipo más grande a nuestra disposición, estábamos bien equipados para ejecutar la migración.


Se sentía como una oportunidad de oro que no podíamos permitirnos perder.


Después de todo, permanecer confinado a la arquitectura monolítica significaría lidiar perpetuamente con sus limitaciones.


La línea de tiempo limitada para expandirse a un nuevo dominio sirvió como catalizador, impulsándonos a construir una arquitectura más escalable y mantenible de inmediato en lugar de tener iteraciones cortas y lentas.


Para ejecutar la migración y manejar simultáneamente el trabajo en el nuevo dominio, dividimos los equipos en dos grupos dedicados. El trabajo de funciones, que tenía mayor prioridad, requería más recursos y necesitaba iterar a un ritmo más rápido.


Para garantizar la integridad y la comprensión integral del proceso de migración, tenía sentido asignar un pequeño equipo dedicado específicamente responsable de manejar la migración.


Sin embargo, no podíamos continuar con el trabajo de características sin antes asegurarnos de que el concepto de micro-frontend resultaría exitoso.


Para mitigar los riesgos y proporcionar una hoja de ruta clara, era crucial crear un documento de diseño de bajo nivel que incluyera estimaciones precisas y una evaluación de riesgos exhaustiva. Este documento sirvió como modelo, describiendo los pasos necesarios y las consideraciones para la migración.


El hito fundamental en este proceso fue el desarrollo de una prueba de concepto que demostraría la integración exitosa de todos los componentes de acuerdo con el diseño.


Este hito, acertadamente llamado "Punto sin retorno", tenía como objetivo validar la viabilidad y eficacia de la arquitectura de micro-frontend.


Si bien era optimista sobre el éxito de la migración, era esencial prepararse para las contingencias. En consecuencia, ideé un Plan B, que actuó como una estrategia de respaldo en caso de que el concepto inicial no diera los resultados deseados.


Esto incluyó la asignación de siete días adicionales en las estimaciones específicamente para tenerme llorando en la almohada más unos días para tener una nueva entrada de módulo de funciones conectada al núcleo a través de carga diferida (¿recuerdas el monolito distribuido?).

El diseño

Al diseñar micro-frontends, generalmente hay 3 enfoques para la composición, cada uno de los cuales se enfoca en dónde tiene lugar la resolución de la aplicación en tiempo de ejecución. La belleza de estos enfoques es que no se excluyen mutuamente y se pueden combinar según sea necesario.

Composición del lado del servidor

La idea básica es aprovechar un servidor proxy inverso para dividir paquetes de micro-frontend por página y realizar una recarga de página basada en la URL de la ruta.

Ventajas:

  • Fácil de implementar


Contras:

  • El estado global no se sincronizará entre las aplicaciones de micro-frontend. Este fue un punto claro para nosotros porque teníamos operaciones en segundo plano de larga duración realizadas en el lado del cliente.


    Podría argumentar que podríamos conservar una instantánea de la "cola" de esta operación en el almacenamiento local y leerla después de la recarga completa, pero debido a razones de seguridad, no pudimos implementar esto.


    Este es solo un ejemplo de un estado global, pero aquí hay otro ejemplo de cómo puede verse: estado de los paneles de navegación lateral (expandidos/contraídos), mensajes de brindis, etc.


  • La actualización dura al navegar a través de microaplicaciones no es muy amigable para el cliente. Hay una forma de almacenar en caché el HTML compartido mediante los trabajadores del servicio, pero es una complejidad adicional de mantener.


  • Costos operativos y de mantenimiento adicionales para la infraestructura: servidor proxy para cada aplicación micro-frontend (esto se puede evitar si se lee directamente desde la CDN), infraestructura separada para implementar dependencias comunes (proveedor) para ser reutilizadas por varias páginas, y correctamente almacenados en caché por los navegadores.

Composición del lado del borde

Otro enfoque para la composición de micro-frontend es la composición del lado del borde, que implica combinar micro-frontends en la capa del borde, como una CDN. Por ejemplo, Amazon CloudFront es compatible con la integración de Lambda@Edge , lo que permite el uso de una CDN compartida para leer y servir el contenido de micro-frontend.

Ventajas:

  • Menos piezas de infraestructura para mantener: no es necesario tener servidores proxy, CDN separados para cada microaplicación


  • Escalamiento virtualmente infinito usando tecnología serverless


  • Mejor latencia en comparación con los servidores proxy independientes


Contras:

  • El tiempo de arranque en frío puede convertirse en un problema


  • Lambda@Edge no es compatible con todas las regiones de AWS si necesita tener una infraestructura de varias regiones (aislada)

Composición del lado del cliente

La composición del lado del cliente es otro enfoque de la arquitectura de micro-frontend que utiliza técnicas de orquestación de micro-frontend del lado del cliente, desvinculadas de la implementación del servidor.


El jugador clave en esta arquitectura es una aplicación de contenedor (shell) que tiene las siguientes responsabilidades:


  • Abordar preocupaciones transversales: la aplicación contenedora maneja el diseño centralizado de la aplicación, la navegación del sitio, el pie de página y el panel de ayuda. La integración con micro-frontends que tienen preocupaciones transversales ocurre a través de un bus de eventos, donde los eventos sintéticos se envían y manejan dentro del alcance de la ventana global.


  • Orquestación de micro-frontends: la aplicación contenedora determina qué paquete de micro-frontend cargar y cuándo, según los requisitos de la aplicación y las interacciones del usuario.


  • Composición de dependencias globales: la aplicación contenedora compone todas las dependencias globales, como React, SDK y bibliotecas de UI, y las expone como un paquete separado (vendor.js) que se puede compartir entre las micro-frontends.


La idea general es que cada paquete de micro-frontend produciría 2 tipos de archivos de activos:

  • {hash}/index.js: sirve como punto de entrada para la aplicación de micro-frontend, con el hash representando un identificador único para toda la compilación.


    El hash actúa como una clave de prefijo para cada paquete en el depósito S3. Es importante tener en cuenta que pueden existir varios puntos de entrada, pero el hash sigue siendo el mismo para todos ellos.


  • manifest.json: este es un archivo de manifiesto que contiene rutas a todos los puntos de entrada para la aplicación de micro-frontend. Este archivo siempre quedaría en la raíz del depósito S3, por lo que el contenedor podría descubrirlo fácilmente.


    Recomiendo activar el control de versiones de este archivo en el depósito S3 para poder observar mejor los cambios. Si está utilizando Webpack para construir su proyecto, le recomiendo encarecidamente WebpackManifestPlugin , que hace todo el trabajo pesado por usted.


El contenedor solo reconoce la URL del dominio de origen del activo de micro-frontend (origen de CDN) en función de la etapa y la región. Durante la carga de la página inicial, el contenedor descarga el archivo de manifiesto para cada aplicación de micro-frontend.


El archivo de manifiesto tiene un tamaño pequeño (~100 bytes) para evitar afectar el tiempo de carga de la página y se escala bien incluso cuando se agregan múltiples micro-frontends dentro de un contenedor. Es crucial considerar el archivo de manifiesto como inmutable en el almacenamiento de caché del navegador para evitar un almacenamiento en caché agresivo.


Elegir la biblioteca de orquestación correcta es el mayor desafío en esta composición y se discutirá en el siguiente capítulo.

Ventajas:

  • Agnóstico a la implementación del servidor: este enfoque se puede implementar sin ningún requisito de servidor específico, lo que ofrece flexibilidad en la tecnología de back-end utilizada. Como se muestra en la imagen de arriba, incluso puede no tener ningún servidor


  • Preservar el estado global: mediante el uso de una aplicación de contenedor (shell), el estado global se puede mantener al cambiar entre micro-frontends. Esto garantiza una experiencia de usuario perfecta y evita perder el contexto durante las transiciones.


  • Enfoque descentralizado: cada micro-interfaz puede decidir de forma independiente qué datos enviar al navegador para iniciarse. La aplicación contenedora simplemente sigue un contrato bien definido, lo que permite una mayor autonomía y modularidad.


  • Configuración local simple: las fuentes de activos se pueden ajustar fácilmente entre la producción y las URL locales en función de las necesidades de desarrollo. El archivo de manifiesto ayuda a la aplicación contenedora a descubrir y cargar las microfrontends requeridas. Los desarrolladores pueden concentrarse en ejecutar solo el contenedor y las microfrontends específicas en las que están trabajando.


Contras:

  • Más saltos de red para obtener el archivo de manifiesto: dado que el contenedor necesita recuperar el archivo de manifiesto para cada micro-interfaz, puede haber solicitudes de red adicionales y latencia potencial en comparación con otros enfoques de composición. Esto se puede mitigar cargando todo el manifiesto por adelantado en la carga de la página inicial o introduciendo algunas técnicas de precarga.


  • Cumplimiento del contrato común: cada micro-frontend debe cumplir con un contrato común para producir compilaciones. Esto se puede facilitar a través de configuraciones compartidas y prácticas de desarrollo estandarizadas para garantizar la coherencia entre las micro-frontends (más sobre esto en las siguientes partes).

Composición híbrida

Como mencioné anteriormente en este capítulo, todos estos patrones de composición se pueden mezclar y combinar dentro de la misma aplicación de shell. Aquí hay un ejemplo de cómo puede verse:

Recomendación

Recomiendo comenzar con un enfoque homogéneo al principio: seleccione un patrón de composición que se adapte mejor a usted y comience a construir la infraestructura a su alrededor.


Para nosotros, la composición del lado del cliente era la mejor opción, pero para el futuro, consideramos cambiar algunas regiones a la orquestación del lado del borde (según la disponibilidad de Lambda@Edge).

Elección de la biblioteca de orquestación

Cuando se trata de implementar la composición del lado del cliente en una arquitectura de micro-frontend, seleccionar la biblioteca de orquestación correcta es una decisión crítica.


La biblioteca elegida jugará un papel crucial en la gestión de la carga dinámica y la coordinación de micro-frontends dentro de la aplicación contenedora.


Existen varias bibliotecas de orquestación populares, cada una con sus propias ventajas y consideraciones.

spa individual

Single-spa es una biblioteca de orquestación ampliamente adoptada que proporciona un enfoque flexible y extensible para la composición de micro-frontend. Permite a los desarrolladores crear una aplicación shell que orqueste la carga y descarga de múltiples micro-frontends.


Single-SPA proporciona un control detallado sobre los eventos del ciclo de vida y es compatible con diferentes marcos y tecnologías.


Ventajas:

  • Independiente del marco: la biblioteca funciona bien con varios marcos frontend como React, Angular, Vue.js y más.


  • Configuración flexible: ofrece potentes opciones de configuración para enrutamiento, carga diferida y dependencias compartidas.


  • Ecosistema robusto: Single-SPA tiene una comunidad activa y un rico ecosistema de complementos y extensiones.


Contras:

  • Curva de aprendizaje: Comenzar con single-spa puede requerir cierto aprendizaje inicial y comprensión de sus conceptos y API.


  • Complejidad de personalización: a medida que la arquitectura micro-frontend crece en complejidad, configurar y administrar la orquestación puede convertirse en un desafío.

Qiankun

Qiankun es una poderosa biblioteca de orquestación desarrollada por el equipo de Ant Financial (Alibaba). Utiliza un enfoque HTML parcial para la composición. En el lado de la aplicación de micro-frontend, produce un fragmento HTML simple con todos los puntos de entrada para cargar.


Después de consumir este archivo HTML, el contenedor hace toda la orquestación y monta la aplicación. En esta configuración, HTML parcial juega el papel de un archivo de manifiesto del que hablé en el capítulo anterior.


Ventajas:

  • Independiente del marco: Qiankun es compatible con varios marcos frontend, incluidos React, Vue.js, Angular y más.


  • Integración simplificada: Qiankun proporciona un conjunto de API y herramientas fáciles de usar para crear y administrar micro-frontends.


  • Escalabilidad y rendimiento: Qiankun ofrece mecanismos eficientes para sandboxing de código, aislamiento de estado y comunicación entre micro-frontends.


Contras:

  • Conflictos de dependencia: la administración de dependencias compartidas y la garantía de la compatibilidad entre micro-frontends pueden requerir una configuración y consideración cuidadosas.


  • Curva de aprendizaje: si bien Qiankun proporciona una amplia documentación, la adopción de una nueva biblioteca puede implicar una curva de aprendizaje para su equipo de desarrollo.


  • Datos redundantes enviados por cable: el fragmento HTML parcial contiene datos redundantes (cuerpo, meta, etiquetas DOCTYPE) que deben enviarse a través de la red.

Federación de módulos

La federación de módulos , una función proporcionada por Webpack, ha ganado una gran atención y entusiasmo en la comunidad de desarrollo web. Esta tecnología permite a los desarrolladores compartir código entre múltiples aplicaciones en tiempo de ejecución, lo que la convierte en una opción atractiva para crear micro-frontends.


Con su perfecta integración con Webpack y la flexibilidad del tiempo de ejecución, Module Federation se ha convertido en una opción popular para administrar y orquestar micro-frontends.


Ventajas:

  • Integración perfecta con Webpack: si ya está utilizando Webpack como su herramienta de compilación, aprovechar Module Federation simplifica el proceso de configuración e integración.


  • Flexibilidad de tiempo de ejecución: la federación de módulos permite la carga dinámica y el uso compartido de dependencias, lo que proporciona flexibilidad en la gestión de micro-frontends.


Contras:

  • Soporte de marco limitado: si bien Module Federation es compatible con múltiples marcos de interfaz, puede requerir una configuración adicional o soluciones alternativas para casos de uso específicos.


  • Soporte de la comunidad: Module Federation es una tecnología relativamente nueva, lanzada como un complemento central en Webpack 5 (y luego retroportado a v4 ). La biblioteca Next.js también es más nueva y se lanzó recientemente como fuente abierta. Al igual que con todas las herramientas nuevas, puede haber una comunidad más pequeña y menos soporte disponible. Es importante tener en cuenta este factor si tiene plazos ajustados o anticipa encontrar preguntas sin respuestas disponibles.

Conclusión

En esta primera parte de la serie "Viaje de migración de micro-frontend", hemos discutido la motivación detrás de la migración de un monolito web a una arquitectura distribuida y los pasos iniciales tomados para vender la idea al liderazgo.


Exploramos la importancia de un documento de visión técnica que mostrara un análisis de rendimiento detallado y describiera las diferentes fases de la migración.


Luego profundizamos en las consideraciones de diseño para micro-frontends, discutiendo tres enfoques: composición del lado del servidor, composición del lado del borde y composición del lado del cliente.


Cada enfoque tiene sus pros y sus contras, y la elección depende de varios factores, como la sincronización del estado global, la experiencia del cliente, la complejidad de la infraestructura y el almacenamiento en caché.


Además, exploramos bibliotecas de orquestación populares, como single-spa, qiankun y Module Federation, destacando sus características, beneficios y desafíos potenciales.


¡Únase a mí en las próximas partes de la serie a medida que continuamos nuestro viaje de migración de micro-frontend, descubriendo información más interesante y valiosa en el camino!


Publicado originalmente en https://thesametech.com el 18 de abril de 2023.


¡También puedes seguirme en Twitter y conectarte en LinkedIn para recibir notificaciones sobre nuevas publicaciones!