Micro Frontends en un Monorepo

5 de mayo de 2022

Organizar el trabajo en un proyecto de desarrollo de software a gran escala en el que varios equipos trabajan al mismo tiempo puede ser complicado de hacer bien.

Este artículo explorará enfoques comunes para la organización, mientras se concentra en micro frontends en una configuración de monorepositorio.

General

Para establecer un poco de contexto, supongamos que estamos creando una aplicación comercial, que usamos en nuestro artículo anterior sobre micro interfaces.

Ejemplo de proyecto frontend.

Como se ve en el diagrama anterior, la aplicación consta de varias secciones separadas que deben ser desarrolladas por equipos separados. Cada equipo puede tener múltiples opciones de pila de tecnología, pero eso no tiene importancia para el tema de este artículo. El aspecto más importante es que múltiples equipos están construyendo una aplicación compleja, cada equipo manejando una parte diferente del sistema.

Enfoques de desarrollo de software disponibles

Hay varias formas de organizar la estructura del proyecto cuando se trabaja en aplicaciones web a gran escala. Este artículo enumera algunos de los más populares y analiza las diferencias entre ellos.

Cada enfoque tiene varias subvariantes. Sin embargo, este artículo se centra en los escenarios más básicos para cada enfoque, mientras menciona brevemente las posibles desviaciones cuando corresponda.

Desarrollo de aplicaciones separadas

El primer enfoque que vamos a investigar es tener aplicaciones separadas. En este método, cada aplicación compuesta se hospedaría en un repositorio separado y se implementaría en una ubicación separada. Es la configuración más flexible cuando varios equipos trabajan para entregar una aplicación compleja.

Desarrollar aplicaciones separadas como un enfoque para el desarrollo de software.

Sin embargo, también viene con algunos inconvenientes importantes. Un inconveniente que vale la pena mencionar es el trabajo repetitivo que implica mantener el repositorio y Canalización de CI / CD. Además, cada aplicación mantendrá su propia lista de dependencias, que es propensa a conflictos de versiones y tiene un efecto negativo en el rendimiento de la aplicación, ya que las dependencias compartidas se incluyen varias veces, a menos que se utilice una estrategia como webpack externals.

Además de eso, la reutilización del código y la aplicación de la coherencia tienen un costo adicional. Para ejemplificar, si quisiéramos extraer un componente común para ser utilizado por múltiples equipos en aplicaciones de gráficos y noticias, necesitaríamos crear un repositorio separado que contenga la biblioteca, publicarlo en algún tipo de registro de NPM y luego extraerlo como un dependencia de terceros en los proyectos. Esto alarga el proceso y hace que la reutilización del código sea menos probable. La razón de esto es que todo el proceso para reutilizar un pequeño fragmento de código es tan largo que eclipsa los beneficios de hacerlo.

Desarrollo de Monorepositorio

El segundo enfoque es el uso de un monorepositorio. Es la mejor opción si un número limitado de equipos está trabajando simultáneamente en la aplicación.

Sin embargo, el enfoque de monorepositorio es más problemático a medida que más equipos trabajan al mismo tiempo. A medida que aumenta la cantidad de equipos, se requiere más planificación, estrategias de ramificación adecuadas y uso de alternancia de funciones. Estas precauciones son necesarias para mantener la aplicación en un estado liberable, lo que permite la implementación de funciones individuales, mientras que los equipos restantes aún están trabajando en otras funciones. Los posibles problemas se pueden evitar poniendo más énfasis en la planificación de la versión, pero la velocidad general de desarrollo se reducirá.

Enfoque monorepositorio para proyectos frontend.

Hay muchos beneficios en el enfoque de un solo repositorio, que uno podría considerar lo opuesto al enfoque de aplicaciones separadas. La reutilización de código es simple y directa, ya que todo el código base vive en un repositorio. Hay una configuración única de CI/CD y repositorio. Además, el espacio ocupado por las bibliotecas de terceros es mínimo y no requiere soluciones complejas como paquetes web externos.

El mayor inconveniente es el hecho de que esta configuración no escala bien cuando hay más equipos involucrados. En otras palabras, cuantos más equipos trabajen en un proyecto organizado en un monorepositorio, más engorroso se vuelve el proceso debido al cuidado adicional que se requiere para colaborar en un solo código base y un solo artefacto de lanzamiento.

Hay algunas variaciones de la configuración del monorepositorio. Uno sería tener una administración de dependencias separada para cada aplicación compuesta, acercándola a una configuración de aplicaciones separada que vive en un solo repositorio. Además de eso, los equipos pueden habilitar el uso compartido de dependencias a través de espacios de trabajo de yarn, donde algunas dependencias se alojan en el nivel raíz.

Micro Frontends en un Monorepositorio

Para contrarrestar algunas de las limitaciones del enfoque de monorepositorio, evalúe micro frontends en un monorepositorio. Las diferencias son limitadas: la mayoría de las fortalezas y debilidades del enfoque de monorepositorio aún se aplican.

Micro frontends en un monorepositorio

Un diferenciador clave que justifica la complejidad añadida de la arquitectura de micro frontends es el hecho de que puede implementar partes de la aplicación (micro frontends) por separado. A diferencia del enfoque de un solo repositorio, en el que se trata de un solo implementable, puede elegir las aplicaciones compuestas que le gustaría lanzar como lo haría con aplicaciones separadas e independientes. Esta capacidad de implementación independiente reduce la necesidad de complicadas técnicas de bifurcación o alternancia de funciones para evitar que cualquier trabajo sin terminar sea visible para los clientes finales.

La capacidad de lanzar partes de la aplicación por separado no tiene un costo cero, ya que se deben configurar los detalles de implementación para cada micro frontend. También puede requerir algo de trabajo adicional desde la perspectiva de la canalización de implementación. Sin embargo, estos costos son menores cuando se comparan con los beneficios.

Todas las demás consideraciones del enfoque de un solo repositorio aún se aplican, ya que nuestras microfrontends se alojarían en un solo repositorio.

Comparación de enfoques de desarrollo de software

A continuación se muestra una tabla que proporciona una descripción general de las diferencias más importantes entre los tres enfoques.

Desarrollo de aplicaciones separadasMonorepoMicro Frontends en un Monorepo
Repo, CI/CD y costo de configuración de implementaciónAltaBajaMedio
Reutilización de códigoAltaBajaBaja
Múltiples equipos trabajando simultáneamenteBajaAltaMedio
Admite versiones parcialesNo
Costos de actualización de dependenciaAltaBajaBaja
Admite actualizaciones por etapasTal vezNoNo
Duplicación de código de terceros en paquetesAltaBajaBaja

Repo, CI/CD y costo de configuración de implementación

Ambos micro frontends en un enfoque monorepo y monorepo producen un costo de configuración inicial considerablemente menor (repo, CI/CD y configuración de implementación) ya que estamos trabajando en un solo repositorio de código. Además, cuando se comparan micro frontends con un monorepositorio, se deben revisar los detalles de implementación del primero cada vez que se agrega uno nuevo.

Con el enfoque de aplicaciones separadas, el equipo debe establecer todas las configuraciones cada vez que se agrega una nueva aplicación compuesta. Eso aumenta enormemente el costo de desarrollo.

Reutilización de código

La reutilización del código es fácil y requiere casi cero gastos generales en una configuración de un solo repositorio. Principalmente implica mover archivos y/o código.

La diferencia es sustancial cuando se compara con aplicaciones separadas, en cuyo caso el equipo debe extraer el código a una biblioteca nueva o existente. Luego, esta biblioteca debe publicarse en un repositorio npm público o privado para que las aplicaciones puedan consumirla. En este caso, todo el proceso implica un lanzamiento adicional de una nueva versión de una biblioteca existente o una biblioteca completamente nueva, lo que es más costoso que simplemente mezclar el código en un monorepositorio. Más importante aún, si el código compartido es tedioso, los desarrolladores tienden a posponerlo, lo que aumenta aún más el costo del desarrollo.

Múltiples equipos trabajando simultáneamente y versiones parciales

Tener aplicaciones separadas otorga el mayor control, minimizando así la cantidad de conflictos, conflictos de fusión y dependencia de alternancia de funciones. En este enfoque, si toda la aplicación se divide según dominios, propiedad de equipos separados, el único lugar donde varios equipos pueden superponerse y chocar son las bibliotecas compartidas. Aparte de eso, el trabajo puede proceder de forma independiente.
Trabajar en un monorepositorio es muy diferente: todo el trabajo se realiza en un solo repositorio y existe una mayor dependencia de las opciones de funciones y las técnicas de bifurcación adecuadas. Teniendo en cuenta que la aplicación debe publicarse como un todo, la planificación adecuada del lanzamiento es complicada pero crucial.

Las micro interfaces en un enfoque de monorepositorio comparten la mayoría de las ventajas y desventajas de un método de monorepositorio, pero permiten implementaciones y lanzamientos independientes de partes de la aplicación. Eso alivia algunas de las complicaciones asociadas con el enfoque de monorrepositorio.

Actualizaciones de dependencia y actualizaciones por etapas

Con o sin micro frontends, en una configuración de monorepositorio, los equipos trabajan con una única base de código. Por lo tanto, los cambios generales, como las actualizaciones de dependencia global, se aplican de una sola vez a toda la aplicación. Ahorra tiempo ya que elimina mucho trabajo repetitivo, pero presenta mayores riesgos ya que no es posible implementar una aplicación parcialmente actualizada. Las actualizaciones parciales pueden ser posibles en el caso de micro interfaces, pero depende de la configuración individual considerando todas las restricciones de herramientas y aspectos de las bibliotecas que uno intenta actualizar.

El polo opuesto son las aplicaciones separadas, donde el equipo tiene que mantener y actualizar cada aplicación compuesta individualmente. Esto agrega bastante sobrecarga a todo el proceso de actualizaciones y mantenimiento, pero permite la implementación gradual de cambios si la biblioteca lo permite en tiempo de ejecución y si no provoca conflictos de versiones con otras partes de la aplicación.

Duplicación de código de terceros en paquetes

Una configuración de monorepositorio facilita la obtención de una única versión de cualquier dependencia de terceros para incluirla en el paquete final. Podemos tener un solo archivo package.json que defina las dependencias o dependencias comunes movidas al shell de la aplicación en el caso de micro interfaces.

La duplicación de código de terceros no es sencilla en el caso de aplicaciones separadas. Cada aplicación compuesta tendría una copia de todas sus dependencias de terceros, lo que haría que el peso total de la aplicación fuera considerablemente mayor. Los equipos pueden implementar el uso compartido de dependencias mediante enfoques como webpack externs, pero esto agrega complejidad adicional y sacrifica la flexibilidad proporcionada por la configuración de la aplicación por separado.

La flexibilidad de desarrollo se resiente en este caso, ya que las versiones de las dependencias estarían vinculadas a las aplicaciones compuestas, lo que dificultaría las actualizaciones. Además, tales relaciones entre aplicaciones compuestas no serían muy obvias y los equipos podrían pasarlas por alto.

Lo que aprendiste

Como se señaló en este artículo, las microfrontends en un monorepo tienen muchas fortalezas y algunas debilidades. Las mejoras más notables sobre el enfoque de monorepositorio de vainilla se encuentran en el área de lanzamiento. Esta mejora tiene el costo de una mayor complejidad de configuración.

Hay algunos casos de uso válidos en los que el uso de micro frontends en un monorepositorio sería preferencial, especialmente cuando un número limitado de equipos está trabajando en el proyecto y la posibilidad de implementar y liberar partes de la aplicación es crucial. Una cosa a tener en cuenta es que esos beneficios deben superar la complejidad y el riesgo adicionales asociados con la implementación de este enfoque innovador.

Un alto nivel de paralelización entre equipos requiere un modelo de lanzamiento flexible y ramificación para contrarrestar los riesgos inherentes de la paralelización. En ese caso, hacer aplicaciones separadas es la mejor opción. Esto tiene un costo, pero sin embargo se ve compensado por la confianza otorgada por las barandillas que ofrece este enfoque.
Por el contrario, cuando la paralelización del equipo es baja, la ecuación se invierte. Las barandillas de desarrollar aplicaciones separadas aún tienen un alto costo, pero ofrecen muy poco valor. Esta es una oportunidad para simplificar, y un enfoque monorepo o una de sus variantes puede ser una buena opción.

Al final, para optimizar el proceso de desarrollo, las organizaciones deben elegir la herramienta adecuada para el trabajo, en el momento adecuado, y reaccionar a las circunstancias cambiantes para obtener el máximo beneficio del tiempo y el esfuerzo invertidos.

Acerca del autor.
Artur Bañas
Hable con un especialista en asistencia comercial