Esta página proporciona una descripción general conceptual de cómo puede crear y publicar nuevas bibliotecas para ampliar la funcionalidad de Angular.

Si encuentra que necesita resolver el mismo problema en más de una aplicación (o desea compartir su solución con otros desarrolladores), tiene un candidato para una biblioteca. Un ejemplo simple podría ser un botón que envía a los usuarios al sitio web de su empresa, que se incluiría en todas las aplicaciones que crea su empresa.

Empezando

Utilice la CLI de Angular para generar un nuevo esqueleto de biblioteca en un nuevo espacio de trabajo con los siguientes comandos.

ng new my-workspace --create-application=false
 cd my-workspace
 ng generate library my-lib

los ng generate comando crea el projects/my-lib carpeta en su espacio de trabajo, que contiene un componente y un servicio dentro de un NgModule.

Para obtener más detalles sobre cómo está estructurado un proyecto de biblioteca, consulte la sección Archivos de proyecto de biblioteca de la guía Estructura de archivos del proyecto.

Puede utilizar el modelo monorepo para utilizar el mismo espacio de trabajo para varios proyectos. Consulte Configuración de un espacio de trabajo de varios proyectos.

Cuando genera una nueva biblioteca, el archivo de configuración del espacio de trabajo, angular.json, se actualiza con un proyecto de tipo library.

"projects": {
  ...
  "my-lib": {
    "root": "projects/my-lib",
    "sourceRoot": "projects/my-lib/src",
    "projectType": "library",
    "prefix": "lib",
    "architect": {
      "build": {
        "builder": "@angular-devkit/build-angular:ng-packagr",
        ...

Puede compilar, probar y filtrar el proyecto con los comandos de la CLI:

ng build my-lib --configuration development
 ng test my-lib
 ng lint my-lib

Tenga en cuenta que el constructor configurado para el proyecto es diferente del constructor predeterminado para proyectos de aplicaciones. Este constructor, entre otras cosas, asegura que la biblioteca siempre se construya con el compilador AOT.

Para que el código de la biblioteca sea reutilizable, debe definir una API pública para él. Esta “capa de usuario” define lo que está disponible para los consumidores de su biblioteca. Un usuario de su biblioteca debería poder acceder a la funcionalidad pública (como NgModules, proveedores de servicios y funciones de utilidad general) a través de una única ruta de importación.

La API pública de su biblioteca se mantiene en la public-api.ts archivo en la carpeta de su biblioteca. Todo lo que se exporta desde este archivo se hace público cuando su biblioteca se importa a una aplicación. Utilice un NgModule para exponer servicios y componentes.

Su biblioteca debe proporcionar documentación (normalmente un archivo README) para la instalación y el mantenimiento.

Refactorización de partes de una aplicación en una biblioteca

Para que su solución sea reutilizable, debe ajustarla para que no dependa del código específico de la aplicación. A continuación, se incluyen algunos aspectos a tener en cuenta al migrar la funcionalidad de la aplicación a una biblioteca.

  • Las declaraciones como componentes y tuberías deben diseñarse sin estado, lo que significa que no se basan en variables externas ni las alteran. Si confía en el estado, debe evaluar cada caso y decidir si es el estado de la aplicación o el estado que administraría la biblioteca.

  • Todos los observables a los que los componentes se suscriban internamente deben limpiarse y desecharse durante el ciclo de vida de esos componentes.

  • Los componentes deben exponer sus interacciones a través de entradas para proporcionar contexto y salidas para comunicar eventos a otros componentes.

  • Verifique todas las dependencias internas.

    • Para las clases o interfaces personalizadas que se utilizan en componentes o servicios, compruebe si dependen de clases o interfaces adicionales que también se deben migrar.
    • Del mismo modo, si el código de su biblioteca depende de un servicio, ese servicio debe migrarse.
    • Si el código de su biblioteca o sus plantillas dependen de otras bibliotecas (como Angular Material, por ejemplo), debe configurar su biblioteca con esas dependencias.
  • Considere cómo proporciona servicios a las aplicaciones cliente.

    • Los servicios deben declarar sus propios proveedores, en lugar de declarar proveedores en el NgModule o un componente. Declarar un proveedor hace que ese servicio tembloroso. Esta práctica permite al compilador dejar el servicio fuera del paquete si nunca se inyecta en la aplicación que importa la biblioteca. Para obtener más información sobre esto, consulte Proveedores que se pueden cambiar de árbol.

    • Si registra proveedores de servicios globales o comparte proveedores en varios NgModules, utilice el forRoot() y forChild() patrones de diseño proporcionados por el RouterModule.

    • Si su biblioteca proporciona servicios opcionales que podrían no ser utilizados por todas las aplicaciones cliente, admita la agitación de árboles adecuada para ese caso mediante el uso del patrón de diseño de token ligero.

Integración con la CLI mediante esquemas de generación de código

Una biblioteca normalmente incluye código reutilizable que define componentes, servicios y otros artefactos angulares (tuberías, directivas, etc.) que simplemente importa a un proyecto. Una biblioteca está empaquetada en un paquete npm para publicar y compartir. Este paquete también puede incluir esquemas que brinden instrucciones para generar o transformar código directamente en su proyecto, de la misma manera que la CLI crea un nuevo componente genérico con ng generate component. Un esquema que está empaquetado con una biblioteca puede, por ejemplo, proporcionar la CLI de Angular con la información que necesita para generar un componente que configura y usa una característica particular, o un conjunto de características, definido en esa biblioteca. Un ejemplo de esto es Esquema de navegación de Angular Material que configura los CDK BreakpointObserver y lo usa con Material’s MatSideNav y MatToolbar componentes.

Puede crear e incluir los siguientes tipos de esquemas:

  • Incluya un esquema de instalación para que ng add puede agregar su biblioteca a un proyecto.

  • Incluya esquemas de generación en su biblioteca para que ng generate puede andamiar sus artefactos definidos (componentes, servicios, pruebas, etc.) en un proyecto.

  • Incluya un esquema de actualización para que ng update puede actualizar las dependencias de su biblioteca y proporcionar migraciones para cambios importantes en nuevas versiones.

Lo que incluya en su biblioteca depende de su tarea. Por ejemplo, puede definir un esquema para crear un menú desplegable que se rellene previamente con datos enlatados para mostrar cómo agregarlo a una aplicación. Si desea un menú desplegable que contenga diferentes valores pasados ​​cada vez, su biblioteca podría definir un esquema para crearlo con una configuración determinada. Los desarrolladores podrían usar ng generate para configurar una instancia para su propia aplicación.

Suponga que desea leer un archivo de configuración y luego generar un formulario basado en esa configuración. Si ese formulario necesita personalización adicional por parte del desarrollador que está usando su biblioteca, podría funcionar mejor como un esquema. Sin embargo, si el formulario siempre será el mismo y no necesita mucha personalización por parte de los desarrolladores, entonces puede crear un componente dinámico que tome la configuración y genere el formulario. En general, cuanto más compleja sea la personalización, más útil será el enfoque esquemático.

Para obtener más información, consulte Descripción general de esquemas y Esquemas para bibliotecas.

Publicando tu biblioteca

Use la CLI de Angular y el administrador de paquetes npm para crear y publicar su biblioteca como un paquete npm.

Angular CLI usa una herramienta llamada ng-packagr para crear paquetes a partir de su código compilado que se pueden publicar en npm. Consulte Creación de bibliotecas con Ivy para obtener información sobre los formatos de distribución admitidos por ng-packagr y orientación sobre cómo elegir el formato adecuado para su biblioteca.

Siempre debe crear bibliotecas para su distribución utilizando el production configuración. Esto asegura que la salida generada use las optimizaciones apropiadas y el formato de paquete correcto para npm.

ng build my-lib
cd dist/my-lib
npm publish

Administrar activos en una biblioteca

A partir de la versión 9.x del ng-packagr , puede configurar la herramienta para copiar automáticamente los activos en su paquete de biblioteca como parte del proceso de compilación. Puede usar esta función cuando su biblioteca necesite publicar archivos de temas opcionales, mezclas de Sass o documentación (como un registro de cambios).

Bibliotecas vinculadas

Mientras trabaja en una biblioteca publicada, puede utilizar enlace npm para evitar reinstalar la biblioteca en cada compilación.

La biblioteca debe reconstruirse con cada cambio. Al vincular una biblioteca, asegúrese de que el paso de compilación se ejecute en modo de observación y que la biblioteca package.json puntos de configuración en los puntos de entrada correctos. Por ejemplo, main debe apuntar a un archivo JavaScript, no a un archivo TypeScript.

Utilice la asignación de rutas de TypeScript para las dependencias entre pares

Las bibliotecas angulares deben enumerar todas @angular/* dependencias como dependencias de pares. Esto asegura que cuando los módulos soliciten Angular, todos obtengan exactamente el mismo módulo. Si una biblioteca enumera @angular/core en dependencies en lugar de peerDependencies, podría obtener un módulo Angular diferente en su lugar, lo que haría que su aplicación se rompiera.

Mientras desarrolla una biblioteca, debe instalar todas las dependencias de pares a través de devDependencies para asegurarse de que la biblioteca se compile correctamente. Una biblioteca vinculada tendrá su propio conjunto de bibliotecas angulares que utiliza para la construcción, ubicadas en su node_modules carpeta. Sin embargo, esto puede causar problemas al compilar o ejecutar su aplicación.

Para solucionar este problema, puede utilizar la asignación de rutas de TypeScript para indicarle a TypeScript que debe cargar algunos módulos desde una ubicación específica. Enumere todas las dependencias de pares que usa su biblioteca en el archivo de configuración de TypeScript del espacio de trabajo ./tsconfig.jsony apúntelos a la copia local en la aplicación node_modules carpeta.

  "compilerOptions": 
    // ...
    // paths are relative to `baseUrl` path.
    "paths": 
      "@angular/*": [
        "./node_modules/@angular/*"
      ]
    
  

Esta asignación asegura que su biblioteca siempre cargue las copias locales de los módulos que necesita.

Usando su propia biblioteca en aplicaciones

No es necesario que publique su biblioteca en el administrador de paquetes npm para poder usarla en sus propias aplicaciones, pero primero debe compilarla.

Para usar su propia biblioteca en una aplicación:

  • Construye la biblioteca. No puede usar una biblioteca antes de que esté construida.

    ng build my-lib
  • En sus aplicaciones, importe de la biblioteca por nombre:

    import  myExport  from 'my-lib';

Construyendo y reconstruyendo su biblioteca

El paso de compilación es importante si no ha publicado su biblioteca como un paquete npm y luego ha instalado el paquete nuevamente en su aplicación desde npm. Por ejemplo, si clona su repositorio de git y ejecuta npm install, su editor mostrará el my-lib importa como faltante si aún no ha creado su biblioteca.

Cuando importa algo de una biblioteca en una aplicación Angular, Angular busca un mapeo entre el nombre de la biblioteca y una ubicación en el disco. Cuando instalas una biblioteca paquete, el mapeo está en el node_modules carpeta. Cuando construye su propia biblioteca, tiene que encontrar el mapeo en su tsconfig caminos.

La generación de una biblioteca con Angular CLI agrega automáticamente su ruta a la tsconfig expediente. La CLI de Angular usa la tsconfig rutas para indicarle al sistema de compilación dónde encontrar la biblioteca.

Si descubre que los cambios en su biblioteca no se reflejan en su aplicación, es probable que su aplicación esté usando una versión anterior de la biblioteca.

Puede reconstruir su biblioteca cada vez que realice cambios en ella, pero este paso adicional lleva tiempo. Construcciones incrementales la funcionalidad mejora la experiencia de desarrollo de bibliotecas. Cada vez que se cambia un archivo se realiza una compilación parcial que emite los archivos modificados.

Las compilaciones incrementales se pueden ejecutar como un proceso en segundo plano en su entorno de desarrollo. Para aprovechar esta función, agregue el --watch bandera para el comando de construcción:

ng build my-lib --watch

El CLI build El comando usa un constructor diferente e invoca una herramienta de construcción diferente para las bibliotecas que para las aplicaciones.

  • El sistema de compilación para aplicaciones, @angular-devkit/build-angular, está basado en webpack, y se incluye en todos los nuevos proyectos de CLI de Angular.
  • El sistema de construcción de bibliotecas se basa en ng-packagr. Solo se agrega a sus dependencias cuando agrega una biblioteca usando ng generate library my-lib.

Los dos sistemas de compilación admiten cosas diferentes, e incluso cuando admiten las mismas cosas, hacen esas cosas de manera diferente. Esto significa que la fuente de TypeScript puede dar como resultado un código JavaScript diferente en una biblioteca construida que en una aplicación construida.

Por esta razón, una aplicación que depende de una biblioteca solo debe usar asignaciones de ruta de TypeScript que apunten al biblioteca construida. Las asignaciones de ruta de TypeScript deben no apuntar a la fuente de la biblioteca .ts archivos.

Construyendo bibliotecas con Ivy

Hay tres formatos de distribución que puede utilizar al publicar una biblioteca:

  • Ver motor (obsoleto)—Formato heredado, programado para su eliminación en la versión 13 de Angular. Utilice este formato solo si debe admitir aplicaciones de View Engine.
  • hiedra parcial (recomendado): Contiene código portátil que pueden consumir las aplicaciones Ivy creadas con cualquier versión de Angular a partir de la v12.
  • full-Ivy: contiene instrucciones privadas de Angular Ivy, que no se garantiza que funcionen en diferentes versiones de Angular. Este formato requiere que la biblioteca y la aplicación estén construidas con el exacto misma versión de Angular. Este formato es útil para entornos en los que todo el código de la aplicación y la biblioteca se crea directamente desde la fuente.

Las nuevas bibliotecas creadas con Angular CLI tienen por defecto el formato Ivy parcial. Si está creando una nueva biblioteca con ng generate library, Angular usa Ivy por defecto sin más acciones de tu parte.

Transición de bibliotecas al formato Ivy parcial

Las bibliotecas existentes, que están configuradas para generar el formato View Engine, no cambian cuando se actualizan a versiones posteriores de Angular que usan Ivy.

Si tiene la intención de publicar su biblioteca en npm, compile con código Ivy parcial configurando "compilationMode": "partial" en tsconfig.prod.json.

Una biblioteca que usa View Engine, en lugar de Ivy, tiene una tsconfig.prod.json archivo que contiene lo siguiente:

"angularCompilerOptions": 
  "enableIvy": false

Para convertir dichas bibliotecas para usar el formato de Ivy parcial, cambie el tsconfig.prod.json archivo quitando el enableIvy opción y agregando la compilationMode opción.

Habilite la compilación parcial de Ivy reemplazando "enableIvy": false con "compilationMode": "partial" como sigue:

"angularCompilerOptions": 
  "compilationMode": "partial"

Para publicar en npm, use el formato Ivy parcial, ya que es estable entre las versiones de parche de Angular.

Evite compilar bibliotecas con código Ivy completo si está publicando en npm porque las instrucciones Ivy generadas no son parte de la API pública de Angular y, por lo tanto, pueden cambiar entre las versiones del parche.

El código Partial-Ivy no es compatible con versiones anteriores de View Engine. Si usa la biblioteca en una aplicación de View Engine, debe compilar la biblioteca en el formato de View Engine configurando "enableIvy": false en el tsconfig.json expediente.

Las aplicaciones Ivy aún pueden consumir el formato View Engine porque el compilador de compatibilidad angular, o ngcc, puede convertirlo en Ivy.

Asegurar la compatibilidad de la versión de la biblioteca

La versión Angular utilizada para construir una aplicación debe ser siempre la misma o mayor que las versiones Angular utilizadas para construir cualquiera de sus bibliotecas dependientes. Por ejemplo, si tenía una biblioteca que usaba Angular versión 12, la aplicación que depende de esa biblioteca debería usar Angular versión 12 o posterior. Angular no admite el uso de una versión anterior de la aplicación.

Angular CLI usa Ivy para crear aplicaciones y ya no usa View Engine. Una biblioteca o una aplicación creada con View Engine no puede consumir una biblioteca Ivy parcial.

Debido a que este proceso ocurre durante la compilación de la aplicación, usa la misma versión del compilador Angular, lo que garantiza que la aplicación y todas sus bibliotecas usen una única versión de Angular.

Si tiene la intención de publicar su biblioteca en npm, compile con código Ivy parcial configurando "compilationMode": "partial" en tsconfig.prod.json. Este formato parcial es estable entre diferentes versiones de Angular, por lo que es seguro publicarlo en npm.

Evite compilar bibliotecas con código Ivy completo si está publicando en npm porque las instrucciones Ivy generadas no forman parte de la API pública de Angular y, por lo tanto, pueden cambiar entre las versiones del parche.

El código Partial-Ivy no es compatible con versiones anteriores de View Engine. Si usa la biblioteca en una aplicación de View Engine, debe compilar la biblioteca en el formato de View Engine configurando "enableIvy": false en el tsconfig.json expediente.

Las aplicaciones Ivy aún pueden consumir el formato View Engine porque el compilador de compatibilidad angular, o ngcc, puede convertirlo a Ivy en la CLI de Angular.

Si nunca antes ha publicado un paquete en npm, debe crear una cuenta de usuario. Leer más en Publicar paquetes npm.

Consumir código Ivy parcial fuera de la CLI de Angular

Una aplicación instala muchas bibliotecas angulares de npm en su node_modules directorio. Sin embargo, el código de estas bibliotecas no se puede empaquetar directamente junto con la aplicación construida, ya que no está completamente compilado. Para finalizar la compilación, puede utilizar el enlazador angular.

Para las aplicaciones que no usan la CLI de Angular, el vinculador está disponible como un complemento de Babel. Puedes usar el complemento de Babel usando el módulo @angular/compiler-cli/linker/babel para incorporar en sus construcciones. Por ejemplo, puede integrar el complemento en una compilación de paquete web personalizado registrando el vinculador como un complemento para babel-loader.

Anteriormente, si corrió yarn install o npm install tuviste que volver a correr ngcc. Ahora, el enlazador solo necesita procesar las bibliotecas una sola vez, independientemente de otras operaciones npm.

El complemento de Babel del vinculador angular admite el almacenamiento en caché de compilación, lo que significa que el vinculador solo debe procesar las bibliotecas una sola vez, independientemente de otras operaciones npm.

La CLI de Angular integra el complemento del vinculador automáticamente, por lo que si los consumidores de su biblioteca están usando la CLI, pueden instalar bibliotecas nativas de Ivy desde npm sin ninguna configuración adicional.