Crear una librería Angular con angular-cli y ng-packagr

Í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.6.0
  • @angular 5.0.1

2. Introducción

Seguro que a estas alturas ya estáis cansados de escucharme decir que una de las grandezas de Angular es que es altamente reutilizable a través de sus módulos y que podemos encapsularlos en librerías para poder ser utilizadas en otros proyectos de Angular.

Mi consejo es que esta librería tenga el mínimo código de HTML y CSS posible y que se centre en la lógica que quiera resolver y una interfaz “fea” de pruebas.

De esta forma podemos implementar una librería con toda la lógica perfectamente testeada y que podremos reutilizar en proyectos de naturaleza Angular como Ionic y con ciertas restricciones también en NativeScript.

Con esto marcamos la separación entre la lógica y la forma de presentar la solución haciendo que cada rol (desarrollador/arquitecto vs diseñador/ux) invierta el tiempo en lo que realmente es productivo.

Ya os digo yo que cuando tengo que tocar CSS y HTML para que la aplicación quede “bonita” me vuelvo altamente improductivo.

3. Vamos al lío

Existen generadores de Yeoman que facilitan la creación de librerías en Angular: uno de ellos es “generator-angular-library” de mattlewis92 y el otro más conocido es “generator-angular2-library” de jvandemo. Ambos pueden ser útiles pero para mí la forma más cómoda es seguir utilizando la misma herramienta que utilizamos para la implementación de aplicaciones con Angular CLI.

El caso es que a día de hoy no existe un soporte oficial del CLI para la creación de librerías; así que nos tenemos que apoyar en un proyecto llamado “ng-packagr” y seguir los siguientes pasos desde cero.

Para la creación de la librería simplemente creamos un nuevo proyecto con el comando ng.

Una vez creado el proyecto podemos abrirlo con el editor de texto y crear un módulo secundario como ya sabemos con la lógica que queramos compartir, en este caso, lo vamos a simplificar al máximo, porque el objetivo es crear una librería no importa tanto el contenido de la misma.

Vamos a crear un componente asociado al módulo:

Y un servicio también asociado al módulo:

Nota: Como ves no perdemos las ventajas de trabajar con Angular CLI pudiendo hacer uso de los comandos de generación.

Ahora editamos el fichero header.service.ts para añadir un método que devuelva el texto del header.

Este servicio lo instanciamos en el componente, para ello editamos el fichero header.component.ts y establecemos el valor en una propiedad del componente.

Ahora editamos el HTML asociado para interpolar esta propiedad:

Y editamos el fichero header.module.ts para permitir a los usuarios de nuestra librería poder hacer uso del componente HeaderComponent, declarándolo en el array de “exports” y establecemos en el array de “providers” el servicio para poder hacer uso de él de forma interna. En caso de permitir hacer uso del servicio de forma externa tenemos que declarar la función forRoot(), como vemos en el siguiente código:

Nuestra librería tiene implementada toda la funcionalidad que queremos compartir, podemos hacer uso del componente en el fichero app.component.html, importarla en el módulo principal y arrancar la aplicación para verificarlo.

Llega el momento de querer compartir nuestra librería con el mundo, o por lo menos con los desarrolladores de nuestra empresa. Para ello necesitamos incluir en nuestro proyecto la siguiente dependencia de desarrollo:

Esta librería necesita que creemos dos ficheros en la raíz del proyecto: el primero llamado “ng-package.json” donde indicamos el esquema que tiene que utilizar la librería y donde se encuentra el segundo de los ficheros:

El segundo fichero “public_api.ts” define todos los exports de nuestra librería y se utiliza para generar los .d.ts adecuados.

Ahora editamos el fichero package.json para poner la propiedad private a false, ya que se quiere publicar en algún repositorio de npm ya sea público o privado, y añadimos en la sección de scrips un “task” de npm para ejecutar la herramienta de empaquetado. Además todas las dependencias del proyecto las ponemos como peerDependencies para que sean tenidas en cuenta por el proyecto que vaya a utilizar nuestra librería:

Ahora simplemente ejecutamos:

Y si el proceso es correcto nos generará una carpeta dist con el contenido de nuestra librería listo para publicar y preparado para soportar AOT; además genera los ficheros d.ts del API, los bundles UMD para su ejecución con SystemJS y los ficheros en es5 necesarios para su ejecución en el navegador.

Ahora solo tenemos que entrar dentro de la carpeta dist y ejecutar “npm publish” con los permisos necesarios en el repositorio corporativo o público que tengamos configurado y la librería ya puede ser consumida por nuestros usuarios, simplemente ejecutando en sus proyectos:

4. Conclusiones

Hasta que exista una solución más oficial por parte de Angular el uso de ng-packagr nos puede ayudar a crear librerías corporativas para reutilizar en nuestros desarrollos con este framework, de una manera muy limpia y cómoda.

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.