El equipo de Angular recientemente facilito un RFC(Solicitud de Comentarios) sobre los componentes independientes o mejor conocidos Standalone Components. Esto es un esfuerzo para hacer que los NgModules sean opcionales. Es importante enfatizar que los módulos no se van a eliminar por completo, ya que muchas aplicaciones de Angular tienen sus bases en NgModules.
Traducción en español del artículo original de Column Ferry Component-First Architecture with Angular and Standalone Components publicado el 23 diciembre 2021
Sobre este tema, Manfred Steyer ya ha empezado a explorar cómo podemos adoptarlo en nuestras aplicaciones, para saber más puedes mirarte su serie de artículos (En inglés): https://www.angulararchitects.io/en/aktuelles/angulars-future-without-ngmodules-part-2-what-does-that-mean-for-our-architecture/
Routing Declarativo
Yo creo que la mejor arquitectura que podemos lograr cuando los Standalone Components sean introducidos, es basarla en routing declarativo (Declarative Routing).
El Declarative Routing es un concepto que hemos visto implementado por paquetes como react-router. Esto significa declarar nuestras rutas como elementos en la plantilla de nuestro componente.
si tu quieres enterarte de las ultimas novedades de Standalone Component, te dejo el siguiente video
En Angular, no tenemos una solución de enrutamiento declarativo compatible oficialmente; sin embargo, Brandon Roberts ha creado un paquete que implementa este concepto en Angular Component Router.
Angular Component Router nos permite definir las rutas a través de nuestra aplicación en nuestros componentes, eliminando la necesidad de configurar el RouterModule en múltiples capas o módulos de nuestra aplicación.
Como los Standalone Components requieren que especifiquemos sus imports en su decorador @Component
, esto podría volverse difícil de manejar. También significa que todavía dependemos de NgModules, lo que dificulta eliminarlos por completo de Angular.
Arquitectura Component-First
¿Qué pasa si simplemente usamos la plantilla de nuestro componente para definir las rutas a través de nuestra aplicación? Fácilmente, podríamos tener una API declarativa para el routing
de nuestra aplicación que admita redireccionamientos, fallbacks
, lazy loading componentes (¡punto importante!) y guards para las rutas.
Esto puede ir aún más lejos. En este momento, podemos definir rutas en cualquier componente de la aplicación, pero ver la configuración completa del routing de la aplicación puede ser complicado.
Con Standalone components, debemos dividir nuestra aplicación por features
o dominios, es decir crearemos una estructura de carpetas/workspace en la que cada feature
tenga su propia carpeta/librería y en su raíz de esta tenemos un route-entry
que sirve de entrada y este contendrá las rutas para esta parte de la aplicación. Un ejemplo de estructura sería:
Podemos ver que tenemos un route-entry
dominio/feature la raíz de nuestra aplicación y que definirá el enrutamiento para esa área de la aplicación. Ahora, cada quien sabrá exactamente dónde buscar cuando necesite encontrar, editar o agregar rutas al sistema.
A partir de aquí, nuestro routing principal únicamente debe apuntar a RouteEntryComonents
.
Seguir este patrón con Standalone Components significa que nuestros componentes son la base principal de nuestras aplicaciones, como deberían ser.
En este punto, podemos decir que Component-First Architecture es donde nuestros componentes definen y manejan la experiencia del usuario en nuestra aplicación.
Cualquier cosa que afecte la experiencia del usuario debe manejarse a través de nuestros componentes, ya que son nuestros componentes con los que interactúa el usuario.
¿Por qué debería importarnos Component-First?
Primero, es importante resaltar que Component-First tiene como objetivo crear un patrón arquitectónico que coloque a los componentes como la fuente de la verdad en nuestras aplicaciones de Angular.
Actualmente, los NgModules actúan casi como orquestadores, conectando la aplicación. Es a partir de los NgModules donde creamos la arquitectura AppModule -> FeatureModules -> SharedModules -> CoreModules.
Esta arquitectura está bien, ya que funciona, es escalable. ¿Pero es exagerado? Posiblemente.
Si bien ngModules presenta una gran separación dentro de la estructura de la aplicación, como CoreModules
y SharedModules
, pero con frecuencia se complican y son difíciles de mantener.
Además, que SharedModules
en particular puede convertirse en el cajón desastre, donde metemos todo y es conduce a una situación en la que necesitamos importar SharedModule
a todos nuestros FeatureModules
, incluso si uno necesita una simple directiva o un solo servicio.
Con Component-First, nuestros componentes deciden por sí mismos lo que necesitan realizar. Pueden inyectar dependencias a través de su constructor
y pueden importar cualquier componente, directiva o pipe que necesiten para funcionar.
Este mayor nivel de granularidad permite que nuestros componentes se concentren en su función, lo que reduce cualquier exceso que podría terminar compilado con el componente.
Otro punto a resaltar es que los componentes en una arquitectura Component-First son completamente tree-shakeable
, eso quiere decir, si no se importan o enrutan, no se incluirán en el paquete final de nuestras aplicaciones.
Actualmente, para lograr el mismo efecto con NgModules, podemos usar el patrón SCAM (Single Component Angular Module) que fue popularizado por Lars Gyrup Brink Nielsen.
Al seguir el patrón de arquitectura Component-First, también reducimos el acoplamiento entre nuestros componentes y NgModules, lo que prepara el camino hacia un Angular verdaderamente sin NgModules.
Todavía podemos mantener la misma capacidad de composición que ofrece NgModules simplemente siguiendo algunas de las mejores prácticas al organizar nuestro código, algo que Angular ya nos tiene bien acostumbrados.
En resumen, si los componentes apuntan a componentes, nuestro mapa mental de nuestra aplicación se vuelve más simple y podemos ver la estructura de componentes en nuestra aplicación y nos permite tener una idea completa.
Dejaremos de preocuparnos de que NgModules agregue dependencias adicionales en sus componentes que quizás no esté esperando porque en Component-First, nuestros componentes dictan sus propias dependencias y esto reduce enormemente curva de aprendizaje y entendimiento, de nuestro código cuando alguien nuevo entra al equipo.