En los últimos años, la comunidad front-end ha estado discutiendo y utilizando activamente el término "micro-frontend" (en adelante, MF). Diferentes empresas comparten sus enfoques para organizar una solución arquitectónica de este tipo, pero hasta ahora hay poca descripción de los problemas que los MF están diseñados para resolver en la Web, los criterios para su aplicabilidad y las limitaciones de uso.
En este artículo, traté de comparar diferentes formas de organizar MF, así como de formular recomendaciones sobre dónde usar qué enfoque.
El artículo puede ser útil tanto para analistas y equipos de desarrollo al diseñar la arquitectura de un proyecto y diseñar procesos, así como para propietarios de productos, ya que la introducción de MF puede proporcionar un desarrollo más manejable.
Antes de pasar a la definición de MF, veamos algunos problemas que se pueden encontrar en los proyectos:
Tienes un gran proyecto . El tamaño de un proyecto suele ser subjetivo y puede determinarse empíricamente por la cantidad de funcionalidad y la cantidad de desarrolladores. Si tiene suficiente trabajo para desconcertar a 1-2 front-enders y al mismo tiempo no "presionarán sus codos", este es un proyecto pequeño, 3-6 es mediano y más de 6-8 ya es grande. .
Tienes un gran equipo . Nuevamente, empíricamente, esto es más de 10 front-enders, el resto de los participantes no cuentan. Como regla general, un equipo de este tamaño ya se puede dividir en subequipos que asumen una funcionalidad específica para el soporte y adquieren sus propios analistas, backenders y control de calidad.
Tienes una gran funcionalidad. Un solo desarrollador solo puede mantener una pieza de código para su subequipo. Refinar el resto del código puede ser costoso debido a la ignorancia del área temática o la complejidad de implementar la lógica de terceros.
el deseo de cambiar la pila;
un requisito de la empresa para apoyar una familia de proyectos relacionados.
¿Cómo se pueden organizar las relaciones entre tanta gente? ¿Cómo se pueden construir procesos en un proyecto de esta escala? ¿Cómo se pueden delinear correctamente las áreas de responsabilidad? Cuantos más problemas haya recopilado, más vale la pena considerar la introducción de un enfoque micro-frontal. Dado que esta es una continuación natural de la tendencia evolutiva en el desarrollo hacia la descomposición del código y el equipo del proyecto.
Por lo tanto, el enfoque de MF es la división de un frente monolítico en bases de código separadas almacenadas en repositorios separados, a los que tienen acceso subequipos separados. Al mismo tiempo, pueden/deben tener sus propios soportes de demostración, pruebas y ciclos de lanzamiento. En consecuencia, el microfrente es una pieza desmontable de la interfaz. No es necesario dividir por página, la funcionalidad puede ser de extremo a extremo (por ejemplo, kit de interfaz de usuario corporativo).
Por separado, vale la pena destacar que los MF son más una decisión organizacional sobre cómo administrar la complejidad del desarrollo en un proyecto grande. Los MF no lo ayudarán a acelerar la interfaz, algunas implementaciones, por el contrario, incluso la ralentizarán. Pero este enfoque acelerará el propio desarrollo debido a la asignación de áreas de responsabilidad y pruebas aisladas.
Por el contrario, vale la pena mencionar la carga diferida en comparación con los MF. Resuelven diferentes problemas, pero a veces la gente piensa que se trata de una sola cosa, porque en ambos casos "dividimos" la aplicación.
La carga diferida resuelve el problema de rendimiento: cómo no obligar al usuario a cargar todo el paquete de front-end, cómo no esperar más de lo necesario y cómo iniciar el front-end en el cliente más rápido y comenzar a interactuar con él antes.
Los MF no resuelven el problema de rendimiento y, a veces, incluso lo exacerban. Pero ayudan a organizar el desarrollo de una manera más cómoda para un subequipo en particular, minimizando los problemas anteriores.
Ahora hablemos sobre el enfoque de combinar MF en una sola aplicación. Independientemente de lo que elija, debe parecer una sola aplicación para el usuario. Puede fusionar tanto en la etapa de ensamblaje como dinámicamente, durante la ejecución del código en el lado del usuario.
Por lo tanto, todas las formas de organizar los MF se pueden atribuir al tiempo de construcción o al tiempo de ejecución. Cada uno tiene sus ventajas y desventajas.
| Tiempo de construcción | tiempo de ejecución |
---|---|---|
Comprobación de tipos | + | - |
Versionado | + | sin sentido |
Despliegue independiente | - | + |
La verificación de tipos juega un papel importante en el desarrollo moderno. Cuando está a cargo de subequipos independientes separados, se convierte en una necesidad. Cómo garantizar la consistencia de los MF, que usen y transmitan datos con precisión en el formato correcto, etc.
Al fusionar microfrentes en el momento de la compilación, no se le priva de la oportunidad de verificar los tipos. En el caso de una unión de tiempo de ejecución, deberá escribir pruebas de integración para que el frente no "explote" repentinamente en la producción.
El control de versiones y la implementación independiente son muy contradictorios:
El control de versiones significa que puede tomar cualquier versión del MF del otro equipo. Esto es especialmente cierto cuando necesita realizar trabajo adicional para actualizar las dependencias del MF-a de otros. Cada equipo elige un mejor momento para actualizar.
El despliegue independiente da más autonomía e independencia a los equipos. Es importante utilizar siempre las últimas versiones de MF. Esto requiere compatibilidad con versiones anteriores.
El control de versiones también se puede implementar con la fusión del tiempo de ejecución, pero esto no es práctico. Tiene sentido ponerse en contacto con el tiempo de ejecución solo por el bien de la implementación independiente, y este último no puede existir junto con el control de versiones.
A continuación, veremos ejemplos de implementaciones específicas de cada enfoque para combinar MF.
La forma más antigua de organizar MF. iframe es una etiqueta especial para pasar la dirección de un recurso que se mostrará en el sitio principal. El resultado es un sitio dentro de un sitio.
De las ventajas , vale la pena señalar la facilidad de implementación, el aislamiento completo de la lógica y los estilos, la capacidad de realizar una implementación independiente y la ausencia de enlaces a marcos.
Estos beneficios tienen un costo en el rendimiento, ya que cada inserción de un iframe genera una carga de recursos. No puede evitar esto: los intentos de depurar y volver a conectar un nodo DOM no guardarán los recursos cargados previamente, tendrá que volver a descargarlos. Puede minimizar la degradación del rendimiento configurando el almacenamiento en caché.
Para hacer esto, debe configurar la invalidación de caché basada en tiempo para recursos inmutables. Afortunadamente, todos los cli modernos listos para usar para los archivos js y css recopilados adjuntan un pequeño hash al nombre. Las desventajas de este método incluyen la incapacidad de los robots de búsqueda para generar iframes para su posterior indexación.
ventajas | Contras |
---|---|
Fácil implementación | Actuación |
Aislamiento de lógica y estilos. | SEO |
Despliegue independiente | |
Marco agnóstico | |
La comunidad front-end ha estado esperando la creación de componentes nativos durante mucho tiempo, pero al final, nunca obtuvieron la popularidad masiva que muchos esperaban. Los tres marcos front-end más populares (React, Vue, Angular) todavía crean componentes a su manera.
A pesar de la capacidad de crear MF en componentes web, no he visto esto en la práctica. Y esto no es casualidad, hay una serie de bloqueadores:
O libs Lit o Stencil no son lo suficientemente populares ni comunes. Además, no hay suficientes especialistas en el mercado que sepan trabajar con ellos o que estén dispuestos a aprender.
Los elementos angulares o vue-custom-element siguen siendo exóticos. En un entorno nativo, no tiene mucho sentido usarlos. Si ya dividió la aplicación, entonces en paquetes npm ordinarios, para que luego pueda conectar los componentes como desee. El uso de componentes web con otros marcos no es razonable porque, junto con los componentes generados, debe conectar una miniversión del marco en el que se escribieron.
Puede ser costoso mover piezas complejas de funcionalidad a componentes web. Dado que deberá configurar la comunicación de su componente con el resto de la aplicación, es posible que no se justifique sacar una página completa en un componente personalizado separado.
Los robots de búsqueda no pueden crear un componente web y esto afectará la optimización SEO.
ventajas | Contras |
---|---|
Adecuado para la funcionalidad transversal | Difícil de implementar |
Compatible con cualquier marco | SEO |
Aislamiento de lógica y estilos. | |
Desarrollar con paquetes npm tiene muchos beneficios. Los desarrolladores simplemente importan los componentes y archivos que necesitan de la biblioteca. Al mismo tiempo, se conserva la escritura en el proyecto, hay versiones. La compilación es óptima: la sacudida de árboles funciona (eliminando el código no utilizado durante la compilación) y los desarrolladores pueden configurar fácilmente la carga diferida.
Sin embargo, este método también tiene sus inconvenientes. En este caso, se verá obligado a mantener la unidad de la pila, así como a mantener versiones de sus MF y sus dependencias transitivas. Por otro lado, esto puede ser una ventaja: al publicar una nueva versión del paquete, otros equipos pueden asumir la tarea de subir la versión de sus dependencias en un momento conveniente para ellos si necesitan introducir funcionalidad adicional o, por el contrario. , quitar algo.
ventajas | Contras |
---|---|
Actuación | No tiene despliegue independiente |
SEO | Pila única |
Comprobación de tipos | |
Versionado | |
Como alternativa a MF en paquetes npm, considere los submódulos de git. De hecho, estos son repositorios dentro de un repositorio, dentro de los cuales también puede haber repositorios. Puede configurar diferentes ramas en submódulos. Por ejemplo, los módulos de funciones pueden tener una rama ficticia sin nada. Esto es necesario para que el montaje sea más rápido y otros módulos no creen efectos secundarios. Las ramas ficticias pueden ser muy útiles para el desarrollo y las pruebas locales.
En cuanto a sus ventajas y desventajas, este enfoque es muy parecido a los paquetes npm. También importamos algo, pero desde una carpeta vecina, y no desde un paquete, y lo usamos.
Echemos un vistazo a las diferencias entre los dos métodos:
Los paquetes de NPM son, de hecho, un microproducto finito y moderadamente aislado con sus propios lanzamientos y versiones. Todo está enfocado a crear una funcionalidad reutilizable. Pero la aplicación puede ser compleja/enrevesada y apestosa, por lo que puede ser bastante costoso empaquetar un monolito grande. Aquí es donde sería razonable considerar los submódulos porque le permiten cortar el repositorio de manera muy aproximada cuando movemos la carpeta a un repositorio separado sin ninguna preparación adicional.
Los paquetes NPM se pueden anidar recursivamente. Los submódulos también, pero a nivel de ensamblaje pueden comenzar a duplicar la funcionalidad si uno de los submódulos se incluye varias veces en diferentes carpetas como un submódulo separado. En este caso, vale la pena usar una estructura de módulo más plana.
Si necesita implementar rápidamente una función en todos los paquetes a la vez, el desarrollo de paquetes cruzados puede ser extremadamente inconveniente. Si bien todo permanece igual en los submódulos, puede realizar ediciones que afecten a otros submódulos. En este caso, es fácil de depurar. Pero al final, no fusionará los cambios en sí mismos: en el nivel de solicitud de fusión, un equipo de terceros cuyo módulo tocó puede requerir que alinee el código con sus reglas.
npm | submódulos git |
---|---|
Reutilización | Corte en bruto de la funcionalidad |
Dependencias anidadas arbitrariamente | Estructura plana |
Desarrollo multiplataforma | Desarrollo con cualquier número de módulos |
single-spa es esencialmente un marco que combina otros marcos. La tecnología increíblemente poderosa, que oculta una gran cantidad de matices, es un tema para un artículo separado.
El esquema es similar a iframe, pero la carga del MF ahora se realiza a través de importación nativa + mapa de importación o a través de Systemjs si se necesitan polyfills.
A diferencia de todos los métodos de organización de MF, este está altamente diseñado para combinar diferentes marcos en sí mismo. Pero vale la pena advertir contra el uso de la tecnología por el bien de la tecnología misma. Si es posible arreglárselas con una pila, debe usarla. El desarrollo puede tener la carga para siempre de mantener un proyecto técnicamente complejo y corregir cualquier error de los efectos secundarios de diferentes aplicaciones. El usuario puede sentir molestias, porque. se aumentará la cantidad de código para descargar al cliente (los núcleos de diferentes marcos para diferentes piezas de funcionalidad + el núcleo del propio spa único y sus complementos).
ventajas | Contras |
---|---|
Despliegue independiente | Amplia documentación, que aún no cubre todos los casos |
Marco agnóstico | Dificultades con el SEO |
Potente CLI | |
Un complemento de webpack 5 que se desarrolló específicamente para crear MF. Tecnología prometedora: un complemento de compilación pequeño para una agrupación más correcta e importaciones dinámicas en tiempo de ejecución.
El esquema casi uno a uno repite un solo spa, pero ahora las importaciones dinámicas se utilizan para cargar MF
ventajas | Contras |
---|---|
Despliegue independiente | nivel bajo |
Fácil realización | |
Compatible con RSS | |
Veamos qué se puede aplicar y para qué:
iframe : una sola inserción para una combinación de incongruentes
componentes web : cuando necesita una pequeña funcionalidad de extremo a extremo sin estar atado a un marco, como un kit de interfaz de usuario corporativo
Paquetes npm : si hay capacidad de reutilización entre proyectos y/o necesita verificar el tipo en el tiempo de compilación
submódulos de git : cuando necesita cortar un proyecto y distribuir áreas de responsabilidad
single-spa : cuando existe una gran necesidad de combinar múltiples marcos indefinidamente, preferiblemente sin SSR
federación de módulos : todos los demás escenarios para el uso de MF, sujeto a la unidad de la pila.
Cada enfoque es bueno a su manera y todo debe tener su lugar. Antes de cambiar a MF, le recomendamos que piense si realmente lo necesita. Cualquiera que sea el enfoque elegido, inevitablemente complicará algo a nivel de desarrollo, CI/CD o rendimiento. Si hay oportunidades para permanecer en una sola pila y una aplicación monolítica, acepte con gusto esta oportunidad.
Y, por supuesto, no te olvides de los usuarios . En última instancia, descargan todos los marcos conectados y soportan posibles errores debido a la integración incorrecta de MF en diferentes piezas de funcionalidad. Las empresas, a su vez, tendrán que pagar por la implementación y el soporte de todo esto.