Búsqueda de sitios web

typescript - Forma correcta de empaquetar una biblioteca de Angular para soportar Angular 8, 9 y 10


Con el lanzamiento de Angular 10, estoy actualizando la versión de Angular utilizada para construir una biblioteca + aplicación de demostración a la versión 10.

Generalmente esto va sin problemas, y la biblioteca sigue siendo compatible con versiones anteriores de Angular, pero esto no parece ser el caso con esta versión (la versión anterior compilada con Angular 9 funciona bien con Angular 8).

Los archivos de definición de TypeScript de salida incluyen:

import * as ɵngcc0 from '@angular/core';

...

static ɵfac: ɵngcc0.ɵɵFactoryDef<QrCodeComponent, never>;
static ɵcmp: ɵngcc0.ɵɵComponentDefWithMeta<QrCodeComponent, "qr-code", never, { "value": "value"; "size": "size"; "errorCorrectionLevel": "errorCorrectionLevel"; }, {}, never, never>;

Lo cual provoca errores como este al consumir en un proyecto de Angular 8:

 ERROR in node_modules/ng-qrcode/lib/qr-code.component.d.ts(7,25): error TS2694: Namespace '"/ngqrcode-ng8-test/node_modules/@angular/core/core"' has no exported member 'ɵɵFactoryDef'.
    node_modules/ng-qrcode/lib/qr-code.component.d.ts(8,18): error TS2314: Generic type 'ɵɵComponentDefWithMeta' requires 6 type argument(s).
    node_modules/ng-qrcode/lib/qr-code.directive.d.ts(13,25): error TS2694: Namespace '"/ngqrcode-ng8-test/node_modules/@angular/core/core"' has no exported member 'ɵɵFactoryDef'.

Creé el proyecto de prueba angular 8 recién usando:

npx @angular/cli@^8 new ngqrcode-ng8-test

Puedes ver mi pull request en progreso para este cambio aquí: https://github.com/mnahkies/ng-qrcode/pull/8

Nota: Ya tengo enableIvy en false en mis opciones del compilador:

"angularCompilerOptions": {
    "enableIvy": false
  }

¿Existe una manera de construir una biblioteca usando Angular v10 que mantenga la compatibilidad con Angular v8?

Respuesta #1

Hay 2 grandes cambios importantes en Angular 10:

  1. 10 requiere tslib 2.0.0 vs. <10 requiere tslib < 2.0.0,
  2. 10 usa typescript 3.9 vs. < 10 requiere typescript < 3.9

No creo que puedas empaquetar una biblioteca para 8, 9 y 10 en un solo paquete :-)

Respuesta #2

Básicamente, se trata de un tema del uso de un motor de compilación en el lado de la biblioteca y en el extremo de la aplicación consumidora. Ivy reemplaza al ViewEngine en las aplicaciones Angular iniciadas desde Angular v9, y la transición se completará con Angular v13, que ya está aquí a finales de 2021. Hablando del soporte de Angular v8, diría que necesitas construir tu biblioteca con Ivy desactivado, lo que significa que ViewEngine está activado (tsconfig.json):

  "angularCompilerOptions": {
    "enableIvy": false,
    ...
  }

Eso se debe a que ViewEngine es la opción predeterminada para las aplicaciones Angular v8, y las bibliotecas compiladas con Ivy no funcionan con aplicaciones compiladas con ViewEngine. Entonces, la segunda parte del problema es cómo se compila la aplicación. Hay una tabla de compatibilidad de motores para 9-11 (desafortunadamente, no encontré la tabla 8-12):

Como ejemplo de compatibilidad de bibliotecas de Angular 7-12, puedo referirme a mi propia biblioteca, ngx-ui-scroll v2: https://github.com/dhilt/ngx-ui-scroll/tree/v2.3.1. En la v2 utiliza un proceso de compilación personalizado basado en rollup con enableIvy: false. En la v3 creo que cambiaré a Ivy y eliminaré el soporte para aplicaciones Angular ViewEngine. Se puede obtener más información sobre bibliotecas en Angular v13 en el blog oficial: Mejoras próximas en la distribución de bibliotecas de Angular.

Otra parte de la historia de soporte es la compatibilidad de las versiones de TypeScript. Una app de Angular v8 puede usar TS v3.4, Angular v13 puede usar TS 4.5, y, créeme, no solo hay cambios incompatibles de v3 -> v4 (por ejemplo, mira esta ruptura de 3.6 -> 3.7). La app debe tener la opción skipLibCheck configurada en true para ignorar tales problemas durante la compilación (tsconfig.json):

  "compilerOptions": {
    "skipLibCheck": true,
    ...
  }

Artículos relacionados