Primeros pasos con Nx

1
8012

Índice de contenidos


1. Entorno

Este tutorial está escrito usando el siguiente entorno:

  • Hardware: Slimbook Pro 13.3″ (Intel Core i7, 32GB RAM)
  • Sistema Operativo: LUbuntu 16.04
  • Visual Studio Code 1.16.1
  • @angular/cli 1.7.1
  • @angular 5.2.7
  • @nrwl/nx


2. Introducción

A poco que te hayas pegado con aplicaciones Angular un poco más complejas te habrás preguntado cuál será la mejor forma de organizar todo tu código y poder hacerlo reutilizable sin morir en el intento.

Una forma de estructurar adecuadamente una aplicación con Angular es dividir la aplicación en distintos módulos por funcionalidad que sean fácilmente «enganchables» con el módulo principal de forma lazy, para no aumentar el tamaño general del bundle.

Cuando hacemos esta división nos podemos dar cuenta que existen elementos que se repiten en los distintos módulos. Es algo muy común establecer un módulo «shared» que almacene todos estos elementos transversales como: pipes, directivas, componentes, servicios, modelo, validadores y guardas del router.

Además podemos darnos cuenta de que algunos de estos elementos nos conviene extraerlos a una librería para que puedan ser importados en otros proyectos de Angular.

Esto requiere de mucha disciplina por parte de los desarrolladores, y sobre todo, de los arquitectos y es fácil encontrarse con la excusa de que estas refactorizaciones llevan un tiempo que muchas veces no se tiene.

Por suerte este tipo de problemas, sobre todo en grandes compañias, es tan común que muchos ex-miembros del core de Angular se han unido en una empresa llamada Nrwl, fundada por Victor Savkin (más conocido por ser el padre del router de Angular y que no hubiera versión 3 del framework); juntos han creado la tecnología Nx que se integra con el CLI de Angular para añadir nuevos comandos (gracias a schematics) que facilitan la organización y el desarrollo de proyectos complejos en un único espacio de trabajo.

Una de las principales características de esta tecnología es que facilita el uso del monorepo, es decir, que todas nuestras aplicaciones y librerías relacionadas con Angular estén en un único repositorio de Git, al estilo de Google, Facebook, o Uber. Las principales ventajas que encontramos son:

  • No enmascara ninguna pieza de código, todo lo que hay se ve en el mismo repositorio, así es más fácil darse cuenta de qué piezas ya están implementadas evitando las re-implementaciones.
  • Permite ejecutar los tests en todo el repositorio, lo que hace que fallen si hay cualquier cambio en alguna librería compartida que afecta a otra, evitando el exceso de código por programación defensiva.
  • Crear una nueva pieza (aplicación/librería) solo supone crear una nueva carpeta en el proyecto, lo que favorece que los desarrolladores queramos modulizar más nuestro código, al no tener que esperar al típico trámite burocrático de crear un nuevo repositorio en la organización y hacer la configuración inicial, lo que puede llevar días, si estamos en el mismo repo, lo podemos hacer en minutos.
  • Las refactorizaciones de código que implican cambios en aplicaciones y librerías también se hacen de forma más sencilla y efectiva al no tener que cambiar el contexto y poder ejecutar los tests de forma conjunta.
  • Solo tenemos una única versión para todos los proyectos por lo que las migraciones a versiones superiores del framework se hacen de manera más eficiente; como Angular saca versión cada 6 meses y deja compatibilidad con la versión anterior, tenemos un año para modificar nuestro código si es que existe algún breaking change.


3. Empezando con Nx

Nota: Toda la información se encuentra en su documentación oficial

Lo primero que necesitamos es instalar de forma global la siguiente dependencia que nos va a permitir poder ejecutar los comandos de nx desde el CLI de Angular:

$> npm install -g @nrwl/schematics

Una vez termine el proceso de instalación tendremos a nuestra disposición el siguiente comando para la creación del workspace:

$> create-nx-workspace nombre-workspace [--directory=nombre-directory] [--npm-scope=nombre-scope-sin-@]

Este comando tiene dos parámetros que son opcionales:

  • directory: para definir un nombre de carpeta distinto al del nombre de workspace.
  • npmScope: para definir un scope de npm distinto al nombre del workspace, del tipo @nombreScope, es importante definirlo sin la @, ya que al tratarse de un scope de npm ya se lo pondrá internamente.

Dentro de este espacio de trabajo recién creado se encuentran dos directorios: uno «apps» que almacena el módulo principal de cada una de las aplicaciones de Angular y otro «libs» que almacena los módulos secundarios y librerías compartidas.

Creación de una nueva aplicación

Para crear una nueva aplicación hacemos uso del comando generate de Angular pasándole el nombre de la aplicación.

$> npm run ng -- generate app nombre-app

Este comando genera la aplicación con el nombre especificado dentro de la carpeta «apps» y modifica automáticamente el fichero .angular-cli.json para registrar la nueva aplicación.

En caso de querer añadir automáticamente el módulo de routing tendremos que añadir el siguiente flag:

$> npm run ng -- generate app nombre-app --routing

Nota:Si entramos dentro del directorio podemos ver que la estructura de esta aplicación no difiere en nada de un proyecto creado con Angular CLI.

Estas aplicaciones serán las encargadas de generar el esqueleto visual de la aplicación, con el módulo principal, la gestión del router para la carga lazy del resto de módulos y el aspecto estético de la aplicación.

Es importante para el rendimiento general que esta aplicación solo contenga lo imprescindible; el grueso de nuestro código tiene que recaer en las librerías.

Creación de una librería como módulo secundario

Para la creación de una librería como módulo secundario tenemos que hacer uso del siguiente comando:

$> npm run ng -- generate lib nombre-module-lib

o si queremos añadir la gestión del router:

$> npm run ng -- generate lib nombre-module-lib --routing

y si queremos que se configure asociado al router de una aplicación y se cargue de forma lazy, tenemos que ejecutarlo con el flag «lazy» e indicando la ruta del módulo principal asociado:

$> npm run ng -- generate lib nombre-module-lib --routing --lazy --parentModule=apps/nombre-app/src/nombre-app.module.ts

Este tipo de librerías van a contener la lógica de las distintas funcionalidades sin preocuparse por el aspecto estético.

Creación de una librería

Para la creación de una librería hacemos uso del flag –nomodule:

$> npm run ng -- generate lib nombre-lib --nomodule

Este comando crea una simple librería sin módulo asociado, la cual se va a encargar de implementar todas aquellas funcionalidades transversales al resto de módulos: como el sistema de notificación de mensajes, el logging, acceso a datos externos, etc… serán susceptibles de extraerse como librerías independientes para su uso en otros proyectos con Angular.

Arranque/distribución de la aplicación

Para poder arrancar o distribuir la aplicación tenemos que especificar con el flag «app» el nombre de la aplicación:

$> npm run start -- --app=nombre-app
$> npm run build -- --app=nombre-app

Cosas a tener en cuenta cuando trabajamos con un workspace de Nx

En este punto donde puede ser que varias librerías y aplicaciones creadas en nuestro workspace, tenemos que tener en cuenta algunos aspectos:

  • Todos los ficheros se referencian con el nombre del workspace. Es decir, cuando vayamos a importar un elemento de una librería dentro de una aplicación debemos hacerlo como @nombre-workspace/path-al-elemento
  • Es importante que a medida que vayamos incluyendo elementos en los proyectos nos acordemos de actualizar el index.ts asociado, a fin de que las importaciones automáticas se realicen de forma correcta.
  • Cuando ejecutamos el comando «npm run test» lo estamos haciendo de todos los tests del workspace, no solo del proyecto en el que estemos trabajando, si queremos ejecutar solo los de nuestro proyecto, tendremos que utilizar fdescribe o bien cambiar la ruta del fichero test.ts especificando solo la ruta a nuestro proyecto.

Aquí tienes un ejemplo de workspace con Nx

Actualizar el workspace a la última versión de Angular

Como ya hemos mencionado una de las grandes ventajas de trabajar con un único repositorio es que las actualizaciones se pueden efectuar de forma más rápida, pero si además Nx lo hace por nosotros pues mejor que mejor. Para ello tenemos que seguir los siguientes pasos:

Instalar la última versión de estas dependencias de forma local al proyecto:

$> npm install --save-dev @nrwl/nx@latest @nrwl/schematics@latest --save-exact

Luego ejecutar el comando de npm habilitado por el workspace:

$> npm run update

En caso de no tenerlo (por tener una versión más antigua de nx) debemos ejecutar:

$> ./node_modules/.bin/nx update

Esto va a recorrer todo nuestro workspace realizando todas las actualizaciones necesarias de forma automática. Incluso nos actualiza el fichero package.json con las tareas de npm que nos falten.

Terminado el proceso instalamos todas las dependencias por si hubiera necesitado introducir alguna nueva:

$> npm install

Visualizar en un gráfico las dependencias entre aplicaciones y librerías

Otra de las cosas que nos ofrece Nx es una manera muy visual de ver las dependencias que tenemos dentro de nuestro workspace.

Para probarlo puedes hacer clone de mi proyecto:

$> git clone https://github.com/raguilera82/nx-radh.git

Nota:No olvides hacer npm install para instalar todas las dependencias necesarias.

Para obtener el gráfico simplemente tenemos que ejecutar el script de npm asociado:

$> npm run dep-graph

Y a día de hoy podemos ver algo parecido a esto:

Los puntos suspensivos indican que la librería se está cargando en modo lazy.


4. Conclusiones

En este tutorial solo hemos visto la punta del Iceberg de lo que ofrece la tecnología Nx que nos permite integrar proyectos de Ionic como aplicaciones dentro de nuestro workspace, hacer uso de ngrx como una librería compartida, entre otras cosas, que iremos explorando en próximos tutoriales.

Recordad que esta técnica y otras muchas más las encontraréis en la guía práctica de Angular y también ofrecemos cursos in-house y online.

Cualquier duda o sugerencia en la zona de comentarios.

Saludos.

1 COMENTARIO

  1. Buenas tardes Rubén, muy buen artículo, estaba interesado en conocer cómo se integran los comandos de Angular CLI con Nx y en mi caso es para generar módulos dentro de la librería, pongamos el caso que tengo una librería denominada auth, dentro de libs, y quiero que ésta tenga un módulo interno denominado shared. He probado a generar el módulo pero me lo genera en la app principal y no en librerías, y cuando me posiciono en la librería y lo genero no me reconoce el módulo padre para hacer el import automático.

    Cuál sería el comando más adecuado? Gracias de antemano.
    Francisco

DEJA UNA RESPUESTA

Por favor ingrese su comentario!

He leído y acepto la política de privacidad

Por favor ingrese su nombre aquí

Información básica acerca de la protección de datos

  • Responsable:
  • Finalidad:
  • Legitimación:
  • Destinatarios:
  • Derechos:
  • Más información: Puedes ampliar información acerca de la protección de datos en el siguiente enlace:política de privacidad