Schematics de Angular: qué son y cómo podemos automatizar tareas (Parte I)

Adrián Martínez, Software Engineer en EDICOM, nos expone en qué consisten los schematics y explica 2 casos de uso que hacemos de ellos. Descubre cómo poder reducir los tiempos de desarrollo de sus aplicaciones usando esta poderosa herramienta. En esta primera parte se explica en que consisten y cómo dejar todo preparado para empezar a programarlos.

    Artículo elaborado por:

    Adrián Martínez

    Software Engineer

    Desarrollador full-stack apasionado del mundo de la programación. Gran interés en Desarrollo de aplicaciones, Material Design y Machine Learning.

Introducción

Los schematics son definidos por el equipo de Angular como: “conjunto de instrucciones para transformar un proyecto de software mediante la generación o modificación de código”.

En la práctica, tal y como se detallará en este artículo, son una herramienta que permite mantener y estandarizar el código de una empresa de una forma automática, por ejemplo, mediante la creación de plantillas de componentes que tenga una estructura similar a otros ya existentes.

Esta guía pretende explicar casos de uso reales de cómo se pueden aplicar, por lo que se puede considerar como una extensión a la documentación aportada por Angular. Se van a explicar todos los pasos necesarios, pero si se quiere profundizar más se recomienda leer:

¿Cómo son usados por Angular?

Antes de explicar cómo se pueden usar a nivel empresarial o personal, vamos a mencionar cómo son usados por el equipo de Angular:

Schematics de adición

Sirven para añadir una librería a un proyecto existente. Lo que hace es que la descarga y ejecuta el script de instalación. Por ejemplo, para instalar la colección de componentes material de angular, el paquete @angular/material, se recomienda hacerlo mediante ng add @angular/material. Que, aparte de añadir la dependencia al package.json, realiza una sería de preguntas y en función a eso modifica los ficheros para configurar correctamente al proyecto.

Schematics de Angular: ¿Qué son y cómo podemos automatizar tareas?
Instalación del paquete @angular/material mediante schematics.

En este caso, por ejemplo, hace falta indicar el tema, tipografía y animaciones que se desean usar.

Schematics de Angular: ¿Qué son y cómo podemos automatizar tareas?
Schematics de Angular: ¿Qué son y cómo podemos automatizar tareas?
Schematics de Angular: ¿Qué son y cómo podemos automatizar tareas?
Cambios realizados en angular.json, index.html, styles.scss y app.module.ts para configurar el proyecto según lo indicado.

Schematics de generación

Estos schematics se ejecutan bajo demanda siempre que el programador los necesite. Tienen 2 casos de uso:

Generación de código a partir de plantillas

Angular proporciona una serie de schematics simples para crear cada una de las entidades existentes. Por ejemplo, el comando ng generate component sirve para crear y declarar un componente simple en base a una plantilla donde las variables sería la ruta y el nombre del componente.

Creación de un base componente mediante el schematic.

Otros schematics de esta categoría sería la colección que dispone Angular Material para generar componentes que usen los componentes proporcionados por esta librería. Por ejemplo, con el comando ng generate @angular/material:navigation crearíamos un componente que usa el sidenav y toolbar.

creación del componente usando el schematic de @angular/material

Al usar este schematic, hay ciertos datos que se sacan automáticamente de la configuración del proyecto como sería el nombre del proyecto. Esto lo hace inspeccionando el código existente.

Código generado por el schematic

Cabe mencionar, que este schematic detecta que el módulo donde se va a declarar el componente no importa los módulos requeridos, así que los importa:

Modificación del app.module tras la ejecución de ambos schematics.
Modificación del código existente

El segundo caso de uso sería cuando el schematic sirve para modificar código existente, pero esto lo hace inspeccionando el propio código actual en lugar de basarse en plantillas para generar código.

Como ejemplo, tendríamos el schematic creado por angular para migrar un proyecto existente a la nueva API standalone. Para realizarlo, sería con el comando ng generate @angular:core/standalone, este en concreto se subdivide en 3 pasos como se explica en su documentación, a modo de ejemplo vamos a analizar la ejecución del primer paso.

Ejecución del schematic de migración.

En el modo standalone, cada componte importa los módulos que son requeridos en lugar de que sean importados en el módulo en el cual el componente es declarado. Lo que hace este paso del schematic es analizar las dependencias de cada componente y añadir la lista de imports requerida.

Modificación del fichero layout.component.ts por el schematic.

Otro ejemplo de estos schematics sería el caso de ng generate @angular/material:mdc-migration, el cual es usado para migrar los componentes legacy del paquete a los nuevos.

Aunque también puede haber un schematic de generación que haga ambas cosas a la vez.

Schematics de actualización

Por último, está los schematics que se ejecutan automáticamente cuando se sube la versión de un paquete. Estos schematics se ejecutarán siempre que el comando usado para actualizar sea ng update PACKAGE_NAME en lugar de npm update PACKAGE_NAME. Para saber qué paquetes de los instalados disponen de un schematic de migración ejecutaremos ng update.

Para este ejemplo, se ha creado un proyecto usando Angular 15, siendo la última versión actualmente la 16. Así que al ejecutar el comando podemos ver:

Ejecución del comando ng update sobre un proyecto con Angular 15.

El comando indica la forma de realizar las actualizaciones de los paquetes disponibles, a modo de ejemplo vamos a ejecutar ng update @angular/core. Este comando, aparte de actualizar en el package.json el paquete, que es lo que haría el comando de npm, actualiza también otra paquetería relacionada como sería zone.js.      

Resultado de la ejecución de ng update @angular/core.

Por último, cabe mencionar que el comando de ng new usado para crear un proyecto desde cero usa por debajo un schematic para proporcionar el código base.

Ventajas de los schematics

Antes de adentrarnos en cómo se programaría un schematic, vamos a mencionar por qué usarlos. Una vez explicados casos reales de ellos, más de uno se puede estar preguntado: “Vale, sirve para modificar una serie de ficheros, ¿por qué debería aprender a usarlos cuando hay herramientas ya existentes con lo que podría conseguir los mismos resultados?”.

Por ejemplo, para crear un componente base se podría haber conseguido algo similar con comandos UNIX como mkdir, touch, cat y echo; y por otra parte, un script que los combine y forme la cadena de código que va en cada fichero.

De la misma forma, se podría modificar el contenido de un fichero mediante la inspección de la cadena de código.

Si bien esto es cierto, se recomienda el uso de schematics por una serie de razones:

  • Se trabaja con un árbol de ficheros virtual y solo cuando todo es correcto se aplica. Por ejemplo, si el script crea un fichero pero este ya existe, el fichero sería sobrescrito. Sin embargo, si esto mismo ocurre en un schematic, se produciría un error que revertiría todos los cambios aplicados. Es decir, se conseguiría no dejar el proyecto en un estado inconsistente.
  • Se evita que se pueda perder código programado. Para poder ejecutar un schematic, el árbol de trabajo de git o de la herramienta de control de versiones usada debe de estar vacío. De esta forma, se consigue que si el resultado de un schematic no es el esperado se pueda revertir sin problemas.
  • Se pueden concatenar schematics con otros sin ningún tipo de problemas.
  • Para la modificación del código actual contamos con las herramientas de análisis de código de Typescript, esto se verá en uno de los ejemplos.
  • Disponemos de funciones ya programadas por Angular que podemos usar en los schematics, como por ejemplo añadir dependencias al package.json o la modificación de ficheros o líneas de código

Todas estas ventajas vienen de serie al usar los schematics, mientras que si se usasen otras herramientas sería responsabilidad del programador toda esta lógica.

Creación de un schematic

Para crear nuestro primer schematic vamos a crear un nuevo proyecto donde incluiremos una colección de schematics. Para ello, haremos uso del comando schematics que viene programado en el paquete @angular-devkit/schematics-cli. Primero, procedemos a instalarlo de manera global mediante npm install -g @angular-devkit/schematics-cli.

Una vez que lo tengamos instalado podemos ejecutar schematics blank –name=schematics, comando que creará un nuevo proyecto bajo la ruta actual donde se podrán encontrar un schematic.

Resultado de la ejecución de schematics blank –name=schematics.

Los ficheros importantes en los que nos centraremos son:

  • collection.json: este fichero se puede considerar la puerta de entrada a todos los schematics que programemos. En él se definirá el nombre de cada uno y la ruta donde está su código. En nuestro proyecto veremos cómo nuestro schematic se llama schematics.
Contenido del fichero collection.json.
  • schematics/index.ts: contiene el código del propio schematic.
Código de nuestro primer schematic.

Para poder ejecutarlo primero tendremos que transpilar el código Typescript, esto ya se nos ha dejado preparado al crear el proyecto. Lo realizaremos con npm run buildl, lo cual creará la versión Javascript de esos ficheros.

Una vez lo tengamos podemos ejecutarlo de la misma que los schematics de los ejemplos previos: schematics PROJECT:NAME, en este caso sería schematics .:schematics. Este comando lo podemos usar porque disponemos del paquete @angular-devkit/schematics-cli globalmente instalado. De no ser así, se tendría que haber lanzado con ng generate .:schematics, que es como lo ejecutarían los usuarios de nuestros schematics.

Si queremos añadir más schematics a la colección lo realizaremos de la misma forma, por ejemplo, schematics blank –name=hello-world. Lo que provoca que se modifique el fichero collection.json para incluirlo y se añada el código bajo la carpeta src.

Creación de un nuevo schematic.

Cabe destacar que al seguir estos pasos se creará un proyecto nuevo que únicamente cuente con los schematics. Si se requiere añadir estos schematics a una librería ya existente se recomienda seguir la guía proporcionada.

Uso de los schematics en un proyecto

Llegados a este punto, ya tenemos que tener configurado un nuevo proyecto que disponga de una colección de schematics. Ahora simplemente nos falta añadirlo a un proyecto ya existente para poder usarlo.

La manera más rápida de conseguirlo y la que se recomienda cuando estemos probando nuestros schematics antes de publicar la versión definitiva sería con el uso del comando link de npm.

Primero nos pondremos en el proyecto transpilado que contiene los schematics y ejecutaremos npm link, a continuación, nos pondremos en la ruta del proyecto donde los queremos usar y ejecutaremos el comando npm link schematics (siendo schematics el nombre del proyecto externo).

Una vez realizados estos pasos, podremos lanzar en ese proyecto los schematics creados, como por ejemplo ng generate schematics:hello-world. Importante destacar que para ejecutarlos no hacemos uso del paquete @angular-devkit/schematics-cli.

Resultado.

Otra alternativa que no exploramos en el artículo, sería publicar el proyecto en un artifactory e instalarlo en cada proyecto, de esta forma todos los programadores los podríamos utilizar. Se recomienda hacerlo así y es como trabajamos en Edicom.

Conclusión

En esta primera parte del artículo nos hemos adentrado en que consiste un schematic, para que sirven y cómo nos los proporciona el equipo de Angular.

Una vez seguida esta guía tenemos que ser capaces de crear una colección de schematics y lanzarlo en un proyecto ya existente.

En el próximo artículo nos adrentraremos en la programación de schematics mediante la explicación de 2 casos de uso que nos han surgiendo en Edicom.

¿Tienes alguna duda o sugerencia? Háznoslo saber escribiendo a rrhhedicom@edicomgroup.com.

Bibliografía