Una de las cosas que se introdujo en Angular 6 fue la capacidad de crear y compilar bibliotecas con la interfaz de línea de comandos de Angular.

Cuando utilicé por primera vez esta función, me encantó lo simple que era, ya que si bien era técnicamente posible crear bibliotecas utilizando versiones anteriores de Angular, fue una experiencia frustrante y triste.

En este artículo, le explicaré los elementos clave del desarrollo de bibliotecas de Angular:

  • Casos de uso comunes para bibliotecas de Angular.
  • Crear una biblioteca usando la interfaz de línea de comandos Angular.
  • Acelerar el desarrollo de bibliotecas angulares con npm link.
  • Publicar su biblioteca.

El código de demostración completo de la biblioteca que creamos se puede encontrar aquí.

Casos de uso para bibliotecas de Angular

Según mi experiencia, hay 2 casos de uso comunes para bibliotecas de Angular:

  1. Creación de una biblioteca de componentes reutilizable para compartir entre aplicaciones.
  2. Crear funcionalidad de capa de servicio compartido, por ejemplo. un cliente para trabajar con una fuente de datos externa como una API.

Si bien hay muchos casos en los que una biblioteca Angular es una buena opción para un proyecto, vale la pena considerar si su caso de uso es uno de estos, ya que introduce cierta sobrecarga de mantenimiento. Recuerde que siempre puede escribir la funcionalidad como parte de un módulo Angular compartido dentro de su aplicación y extraerla en una biblioteca cuando sea necesario.

Crear un proyecto de biblioteca Angular

Crearemos una biblioteca Angular, así como una aplicación de demostración para consumir esta biblioteca. Podemos crearlos con los siguientes comandos:

ng new example-component-library --create-application=falsecd example-component-libraryng generate library example-component-libraryng generate application example-component-library-app

Usando la bandera --create-application=false evita que Angular cree una aplicación con el nombre ‘biblioteca de componentes de ejemplo’, que es el nombre que queremos dar a la biblioteca en sí y no a la aplicación de prueba, como se explica aquí.

Si ahora miramos dentro del espacio de trabajo que acabamos de crear, podemos ver que hay una carpeta projects que contiene una subcarpeta para cada una de las bibliotecas (ejemplo-componente-biblioteca) y la aplicación (ejemplo-componente-biblioteca-aplicación) que acabamos de generar. También hay una tercera carpeta que contiene un proyecto de prueba e2e, que podemos ignorar.

Ahora construyamos nuestra biblioteca y veamos qué sucede:

ng build --project=example-component-library

Si miramos en la carpeta dist, veremos que nuestra biblioteca se ha construido y que dentro de la carpeta de compilación tenemos una serie de carpetas diferentes que contienen la aplicación en varios formatos de módulo diferentes adecuados para diferentes consumidores, así como una carpeta que contiene definiciones de TypeScript.paquetes

  • – Formato de módulo UMD.
  • formato de módulo esm5 que utiliza principalmente es5, pero también la sintaxis de importación / exportación de es6.
  • esm2015 – formato de módulo que utiliza es2015 / es6.
  • fsm5-versión aplanada de esm5.
  • fesm2015-versión aplanada depeerDependencies esm2015.
  • definiciones de lib-TypeScript para la biblioteca.

Este formato se llama Formato de paquete Angular, y es el formato utilizado como salida de ng-packagr, la herramienta que Angular CLI utiliza para transpilar bibliotecas.

Estructuración de su proyecto de biblioteca Angular

El contenido de la biblioteca actualmente se ve así:

Estructura de carpetas Inicial

Primero, elimine los archivos de módulo, componente y servicio example-component-library: no los necesitamos.

A continuación añadiremos un componente, una tubería y una directiva. Seguiremos un patrón de agregar un componente por módulo, esto permitirá que una aplicación consumidora importe solo los módulos de la biblioteca en los que está interesada, y luego que todos los demás módulos se sacudan durante el proceso de compilación. Recomiendo encarecidamente hacer esto, ya que realmente marcará la diferencia en el tamaño de los paquetes de aplicaciones a medida que la biblioteca crezca.

ng generate module components/foong generate component components/foong generate module pipes/barng generate pipe pipes/bar/barng generate module directives/bazng generate directive directives/baz/baz

Después de hacer esto, nuestra biblioteca debe tener la siguiente estructura de carpetas:

Estructura de carpetas Final

Por supuesto, esta estructura se puede ajustar según sus preferencias o las de su equipo, pero las cosas importantes a tener en cuenta son:

  • para sacudir los árboles de los módulos/componentes no utilizados.

    La excepción a esto es que los componentes que siempre se usan juntos deben mantenerse en el mismo módulo, por ejemplo. Si estuviera implementando pestañas, un componente de grupo de pestañas y un componente de grupo de pestañas vivirían en el mismo módulo.

  • Intente evitar o limitar el uso de importaciones de barril dentro de una biblioteca Angular

    En Angular 6 hay problemas con las importaciones de barril en las bibliotecas y la compilación de Angular AOT. Estos problemas parecen arreglarse en Angular 7, pero todavía me encuentro con problemas confusos debido a las importaciones de barriles y, por lo tanto, apoyo esta recomendación de usar solo 1 nivel de importaciones de barriles (o simplemente evitarlos por completo).

A continuación debemos agregar cada uno de los componentes que creamos al exportsde su módulo:

import { CommonModule } from '@angular/common';import { FooComponent } from './foo.component';import { NgModule } from '@angular/core';@NgModule({ declarations: , imports: , exports: })export class FooModule { }

Ahora actualizamos public_api.ts para exportar cualquier archivo de la biblioteca que deseemos exponer a una aplicación consumidora:

/* * Public API Surface of example-component-library */export * from './lib/components/foo/foo.module';export * from './lib/components/foo/foo.component';export * from './lib/pipes/bar/bar.module';export * from './lib/pipes/bar/bar.pipe';export * from './lib/directives/baz/baz.module';export * from './lib/directives/baz/baz.directive';

Ahora todo lo que tenemos que hacer es reconstruir la biblioteca, y estará lista para consumir la biblioteca desde una aplicación.

ng build --project=example-component-library

Consumir nuestra biblioteca Angular

Durante el desarrollo, la mejor manera de consumir nuestra biblioteca es utilizando npm link. Esto nos permitirá enlazar simbólicamente desde un directorio en la carpeta de módulos de nodos de nuestra aplicación consumidora a la aplicación compilada en la carpeta dist de la biblioteca.

cd dist/example-component-librarynpm link

Podemos vincular un proyecto Angular a esta biblioteca desde cualquier lugar de nuestra máquina local. Desde la carpeta raíz del proyecto:

npm link example-component-library

Si ahora dirigimos la biblioteca con el reloj de la bandera, y al mismo tiempo ejecutar ng serve en otra ventana de terminal.

ng build --project=example-component-libraryng serve

Esto nos permitirá desarrollar una aplicación y (una o más) bibliotecas vinculadas simultáneamente, y ver la recompilación de la aplicación con cada modificación del código fuente de la biblioteca.

En Producción

Para producción, publicaremos nuestra biblioteca en npm y luego la instalaremos en la aplicación utilizando npm install.

Primero, deberá crear una cuenta npm. Ahora inicie sesión desde la línea de comandos:

npm login

Desde la carpeta raíz del proyecto:

cd dist/example-component-librarynpm publish

Nuestro paquete ahora está publicado en npm (públicamente), y podemos instalarlo agregándolo a las dependencias package.json y ejecutando npm install:

"dependencies": { ... "example-component-library": "~0.0.1"}

dependencias de la Biblioteca

Si su biblioteca tiene dependencias, a continuación, estos deben ser especificados como dependencies o peerDependencies en el package.json de su biblioteca (y no el package.json en la raíz del proyecto). Por ejemplo, en el caso de nuestra biblioteca simple, solo tenemos las siguientes dependencias:

"peerDependencies": { "@angular/common": "^7.1.0", "@angular/core": "^7.1.0"}

Angular se especifica como peerDependencyen lugar de dependency para evitar que la aplicación consumidora instale varias versiones conflictivas de Angular. Este artículo tiene buena información sobre peerDependencies y cuando utilizarlos.

Conclusión

Hemos visto cómo podemos crear una biblioteca de componentes Angular que puede ser consumida por múltiples aplicaciones Angulares diferentes, así como cómo podemos trabajar con bibliotecas en desarrollo y publicarlas para producción. A continuación, he enumerado los recursos que he encontrado útiles para aprender sobre las bibliotecas de Angular y para escribir este artículo.

Deja una respuesta

Tu dirección de correo electrónico no será publicada.