typescript - Korrekt måte å pakke et Angular-bibliotek på for å støtte Angular 8, 9 og 10


Med utgivelsen av Angular 10 oppdaterer jeg versjonen av Angular som brukes til å bygge et bibliotek + demoapplikasjon til versjon 10.

Generelt går dette glatt, og biblioteket forblir kompatibelt med tidligere versjoner av Angular, men dette ser ikke ut til å være tilfelle med denne utgivelsen (forrige versjon bygget mot Angular 9 fungerer fint med Angular 8).

De genererte TypeScript-definisjonsfilene inkluderer:

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>;

Som forårsaker feil som dette når man bruker det i et Angular 8-prosjekt:

 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'.

Jeg laget testprosjektet i Angular 8 helt ferskt ved å bruke:

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

Du kan se min WIP pull request for denne endringen her: https://github.com/mnahkies/ng-qrcode/pull/8

Merk: Jeg har allerede enableIvy false i kompilatorinnstillingene mine:

"angularCompilerOptions": {
    "enableIvy": false
  }

Finnes det en måte å bygge et bibliotek med Angular v10 som opprettholder kompatibilitet med Angular v8?

Svar #1

Det er 2 store gjennombruddsendringer i Angular 10:

  1. 10 krever tslib 2.0.0 vs. <10 krever tslib < 2.0.0,
  2. 10 bruker typescript 3.9 vs. < 10 krever typescript < 3.9

Jeg tror ikke du kan pakke en lib for 8, 9 og 10 i én enkelt pakke :-)

Svar #2

I utgangspunktet handler dette om en byggemotor som brukes på bibliotekssiden og på sluttbrukerapplikasjonssiden. Ivy erstatter ViewEngine i Angular-applikasjoner som startet fra Angular v9, og overgangen skal være fullført med Angular v13, som allerede er her ved slutten av 2021. Når det gjelder støtte for Angular v8, vil jeg si at du må bygge biblioteket ditt med Ivy slått av, noe som betyr at ViewEngine er på (tsconfig.json):

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

Det er fordi ViewEngine er standardalternativet for Angular v8-applikasjoner, og Ivy-kompilerte biblioteker fungerer ikke med ViewEngine-kompilerte apper. Så den andre delen av problemet er hvordan appen er kompilert. Det finnes en motor-kompatibilitetstabell for 9-11 (dessverre fant jeg ikke 8-12-tabellen):

Som et eksempel på Angular 7-12 bibliotekkompatibilitet kan jeg referere til mitt eget bibliotek, ngx-ui-scroll v2: https://github.com/dhilt/ngx-ui-scroll/tree/v2.3.1. I v2 bruker det en tilpasset rollup-basert byggeprosess med enableIvy: false. I v3 tror jeg at jeg vil bytte til Ivy og droppe støtte for Angular ViewEngine-applikasjoner. Mer informasjon om biblioteker i Angular v13 kan tas fra den offisielle bloggen: Upcoming improvements to Angular library distribution.

En annen del av støtteshistorien er kompatibilitet med TypeScript-versjoner. Angular v8-app kan bruke TS v3.4, Angular v13 kan bruke TS 4.5, og, tro meg, det finnes ikke bare v3 -> v4 brytende endringer (for eksempel se på denne 3.6 -> 3.7 brytningen). Appen må ha skipLibCheck-alternativet satt til true for å ignorere slike problemer under kompilering (tsconfig.json):

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

Relaterte artikler