DEV Community

Cover image for Angular Standalone Components y su impacto en la modularidad
Dany Paredes
Dany Paredes

Posted on

Angular Standalone Components y su impacto en la modularidad

Traducción en español del artículo original de Rainer Hahnekamp @rainerhahnekamp "Angular Standalone Components and their impact on modularity" publicado el 10 enero 2022

Una de las próximas características de Angular será "Standalone Components" (SC) y se puede ver también como "Optional NgModules". Esto eliminará la necesidad de NgModules.

Hay muchas entradas de blog, artículos, etc. sobre SC. Este artículo responde a una pregunta que no se discute tan a menudo: ¿Cómo afectará SC a la modularidad en una aplicación Angular?

La palabra NgModule contiene el término módulo, entonces cuando SC hacen que los NgModules sean opcionales o quizás los desapruebe a largo plazo, ¿significa eso que ya no tendremos módulos? Teniendo en cuenta que Angular es un framework empresarial, y el continuo esfuerzo del equipo de Angular por la estabilidad, esto sería un movimiento inesperado.

Empezaré con un resumen de lo que son los SC y las ventajas que aportan. Después me centro en la cuestión principal, es decir, si los NgModules opcionales y la modularidad forman una contradicción. La última parte trata de la mejor manera en que podemos prepararnos para SC en este momento.

El código fuente está disponible en GitHub.

Puedes ver la versión en vídeo en Inglés: https://youtu.be/rproG1_TCek

¿Qué son los Standalone Components?

Los debates en torno a los SC llevan varios meses en la comunidad. Igor Minar, uno de los desarrolladores clave detrás de Angular, dijo que había querido tratar con NgModules desde la primera versión beta de Angular. Esto fue en 2016. Por lo tanto, fue todo un acontecimiento cuando Pawel Kozlowski publicó la RFC oficial para Standalone Components en GitHub.

El elemento clave en Angular es el componente. Cada componente pertenece a un NgModule que proporciona las dependencias para él. Las declaraciones de propiedades del decorador de un NgModule crean esta relación.

Por ejemplo, si el componente requiere la directiva formGroup, el NgModule suministra esa directiva a través del ReactiveFormsModule.

La misma regla se aplica a los otros elementos visuales que son Pipe y Directive, para mayor simplicidad estos dos se incluyen cuando hablamos de un componente.

Esto no es únicamente una sobrecarga adicional. Dado ese vínculo adicional entre Componente y Módulo y el hecho de que un NgModule puede declarar múltiples componentes, no es tan fácil averiguar qué dependencias requiere un componente en particular.

NgModule declarando múltiples Componentes

Además de los componentes, también hay que tener en cuenta los Servicios y sus tres formas diferentes de proporcionarlos. El NgModule puede hacerlo, el componente puede hacerlo, o el Servicio podría proporcionarse a sí mismo a través de la propiedad providedIn. La última opción es la preferida y fue introducida en Angular 6.

Así, vemos que incluso un solo componente que contenga un formulario y un servicio implica un nivel de complejidad relativamente alto.

Componente con NgModule y un Servicio

Los Standalone Components eliminan la capa adicional del NgModule.

El decorador de un componente recibirá propiedades adicionales para ello y proveer los servicios también será más fácil, ya que solo habrá dos opciones.

Standalone Component

¿Cómo modularíamos nuestra aplicación con los componentes autónomos?

Aquí nos surgen unas preguntas. ¿Permiten los NgModules la modularidad en las aplicaciones Angular? Y si es así, ¿Deberíamos ahora escribir nuestras aplicaciones sin módulos?

Vamos a responder una a una.

¿Qué es un módulo?

Una buena definición de un módulo sería un grupo de elementos en una aplicación que pertenecen juntos. Hay diferentes posibilidades de "pertenecer juntos". Podría ser un grupo que contenga únicamente componentes de presentación, un grupo que contenga todos los elementos relevantes para el estado de NgRx, o algún otro criterio.

La funcionalidad más importante de un módulo es la encapsulación. Un módulo puede ocultar ciertos elementos del exterior. La encapsulación es clave para una arquitectura estable porque evita que cada elemento acceda a cualquier otro elemento.

¿Es NgModule un módulo?

Entonces, en ese sentido, ¿Es NgModule un módulo? Desafortunadamente, el NgModule cumple estos requisitos solo parcialmente. Proporciona encapsulación al menos para los elementos visuales (Componente, Directiva, Pipes) pero no puede imponerlos. Teóricamente, puedo crear un componente que extienda de uno encapsulado, crear un nuevo selector y voilà. Nada me impide acceder a una clase no exportada.

import { Component } from '@angular/core';
import { EncapsulatedComponent } from './module/encapsulated.component';

@Component({
 selector: 'app-stolen',
 templateUrl: './module/encapsulated.component.html',
})

export class StolenComponent extends EncapsulatedComponent {}
Enter fullscreen mode Exit fullscreen mode

Ejemplo de un Componente extendido desde otro encapsulado

La cosa no mejora con los servicios. Como se ha descrito anteriormente, estos pueden vivir fuera del control de un NgModule.

Dado que los NgModules no pueden ofrecer una modularidad completa, ya podemos responder a la pregunta principal de este artículo: Los Standalone Components o los Módulos Opcionales no tendrán un impacto en la modularidad de una aplicación.

Sin embargo, ahora tenemos una nueva pregunta: ¿Qué deberíamos haber usado para los módulos en todo este tiempo?

¿Cómo implementar módulos en Angular?

Hay algo más en Angular además de NgModule, pero se disfraza con un nombre diferente. Es la librería o simplemente lib. Desde Angular 6, el CLI de Angular soporta la generación de librerías.

Una librería tiene su propia carpeta junto a la carpeta de la aplicación real. La librería también tiene un archivo llamado index.ts donde ocurre la encapsulación. Todo lo que se exporta desde ese index.ts se expone al exterior. Esto puede ser Servicios, Interfaces TypeScript, funciones, o incluso NgModules.

Una nota sobre los NgModules en las librerías: Hasta que SC esté disponible, seguimos necesitando el NgModule para exponer los componentes. Por eso una librería incluye también NgModules.

export { Lib1Module } from './lib/lib1.module';
export { ExposedComponent } from './lib/exposed.component';
export { RootProvidedService } from './lib/services/root-provided-service';
export { ExposedService } from './lib/services/exposed.service';
Enter fullscreen mode Exit fullscreen mode

index.ts exponiendo NgModule

¿Qué pasa con la aplicación de la encapsulación?

Puede ocurrir en cualquier momento que un desarrollador importe un archivo no expuesto de una librería. Con un editor moderno eso puede ocurrir muy rápidamente. A menudo vemos esto cuando los elementos no expuestos se importan a través de una ruta relativa, mientras que los expuestos se importan utilizando el nombre de la librería.

Error linter debido a la importación de muchos niveles

Desafortunadamente, no hay nada en el CLI de Angular que nos impida hacer eso. Ahí es donde entra nx. Nx es una extensión de la CLI de Angular y proporciona, entre muchas características, una regla de linting para la modularidad. Esta regla de linting lanza un error si se produce la llamada importación profunda, es decir, el acceso directo a un archivo no expuesto.

Te recomiendo este excelente artículo en ingles para saber mas sobre Nx.

Nx proporciona otra regla de linting donde también podemos definir reglas de dependencia entre módulos. Podemos crear reglas como que el módulo A puede acceder al módulo B y C, pero el módulo B sólo puede acceder a C. Estas reglas también se validan mediante linting.

Por lo tanto, es la librería junto a nx y no el NgModule es la que cumple con todos los requisitos de un módulo.

¿Cómo me preparo mejor para la migración?

Todavía no tenemos SC, pero ¿podemos prepararnos ahora para que la migración sea lo más suave posible?

Durante bastante tiempo, y mucho antes de que se anunciaran los SC, el patrón Single Component Angular Module o "SCAM" ha sido popular en la comunidad. Con SCAM, un NgModule declara sólo un componente.

Si ya utilizas SCAM, el esfuerzo para migrar a SC será probablemente sólo mover las propiedades de los imports y providers al decorador @Component. Un script puede hacer esta tarea automáticamente. Puedes encontrar más información aquí.

¿Debe aplicar SCAM a una aplicación existente?

Si tienes una gran aplicación y un gran deseo de pasar a SC lo más rápido posible, entonces SCAM puede ayudarte a conseguirlo. En general, yo esperaría hasta que se publique SC.

También hay un shim que proporciona SC en este momento, aunque es sólo para fines de demostración y no es seguro para la producción.

Resumen

La gestión de la dependencias en Angular viene con diferentes variaciones y esto puede reducir potencialmente la consistencia, lo cual sera obstáculo para los recién llegados a Angular. El NgModule, en particular, crea una sobrecarga innecesaria y los componentes independientes (NgModules opcionales) eliminarán los NgModules y serán una gran mejora.

Los NgModules opcionales no tendrán esencialmente ningún impacto en la modularidad proporcionada por las librerías. Para las aplicaciones que siguen el patrón SCAM, un script puede hacer la migración automáticamente. Sin SCAM, tendrás que hacerlo manualmente.

Me gustaría dar las gracias a Pawel Kozlowski por revisar este artículo y proporcionar valiosos comentarios.

Nota personal: Gracias a Rainer por permitirme traducir a español su excelente contenido, que responde a muchas preguntas sobre Standalone Components.

Lecturas recomendadas:

En Español:
- Arquitectura de Component-First con Angular y Standalone Components

En Ingles:

Foto de Amélie Mourichon en Unsplash

Discussion (0)