Developer Dagboek #2 – Angular Applicaties Upgraden – Deel I

Angular Applicaties Upgraden

Auteur: Danny Holstein

Ieder half jaar publiceert het Angular Development team een nieuwe grote versie van Angular. Frontend developers die met Angular werken, kunnen bestaande applicaties upgraden naar de nieuwste versie om zodoende te kunnen werken met de nieuwste features en optimalisaties.

Na verloop van tijd worden er ook vulnerabilities ontdekt in de onderliggende packages van Angular. Het is in zulke gevallen een goed idee om onderhoud uit te voeren voor een applicatie. De makkelijkste manier om dit te doen is met de commando’s: npm audit fix - of: npm audit fix --force – zie afbeelding onder:

Angular vulnerabilities

De 2 bovenstaande commando’s voeren geen upgrade uit. Dat wordt wel gedaan met de 2 commando’s: ng update en npm update. Maar als het al een lange tijd geleden is dat er onderhoud is uitgevoerd, dan zijn deze 2 commando’s onvoldoende. De nieuwe features worden niet automatisch toegevoegd (zoals de read-only en Writable signals).

In dit blogbericht bespreek ik kwesties die zich voordeden tijdens het upgraden van Angular applicaties en de ontwikkeling van mijn eigen Angular migratie tool voor versie 17 en verder. Deze tool voorkomt onder andere ook veel typewerk. En er hoeft niet in ieder component handmatig veranderingen toegepast te worden en dit bespaart tijd.

Angular migration tool in development

NPMJS – overzicht van packages

Een goed startpunt is de website https://www.npmjs.com/ - en deze website biedt informatie over de meest recente versies van packages en zijn dependencies.

Een probleem dat zich voordeed was onder andere dat Angular alleen werkt met een specifieke versie van TypeScript. Bijvoorbeeld: Angular 18.2.11 kan met TypeScript 5.5.4 worden geïnstalleerd. Wanneer er een bijvoorbeeld TypeScript versie van 5.6.3 of hoger wordt gebruikt, dan zal de waarschuwing ‘Could not resolve dependency’ in de terminal verschijnen.

Angular dependencies error NPM

Angular modules zijn optioneel

In Angular 16 en eerdere versies dienden modules om gerelateerde functionaliteit te groeperen (zoals: componenten, services, pipes en andere modules). Maar sinds de introductie van standalone componenten is het gebruik van modules optioneel, want een applicatie kan ook alleen met componenten worden gemaakt. In Angular 17 en latere versies wordt er meer functionaliteit in app.config.ts geplaatst in plaats van modules.

Populaire Angular libraries voeren deze verandering ook door. Waarbij modules worden vervangen door standalone-componenten. Het gevolg hiervan is dat deze standalone componenten nu worden toegevoegd in de imports-array van een andere component. Mijn Angular migratie tool verwijdert automatisch modules die niet meer nodig zijn.

Standalone componenten

In Angular 19 zijn componenten, directives en pipes standaard standalone. Een standalone-component is eigenlijk een hybride component-module. Mijn Angular migratie tool kan van alle componenten een standalone component maken (voor Angular 18 en eerder) door in de @Component decorator standalone: true toe te voegen. Het is namelijk voor een groot project ondoenlijk om dit te kopiëren en te plakken in ieder component. Voor Angular 19 kan dit ook weer worden weggehaald.

Angular standalone component

De nieuwe control flow

In een eerder blogbericht heb ik over de nieuwe control-flow geschreven (Angular 18 – Een tussenstand en korte terugblik). Dit is toe te passen met het commando: ng generate @angular/core:control-flow – waarmee de HTML-templates worden gemigreerd.

De ‘oude’ structurele directives (zoals *ngIf en *ngFor) bevinden zich in het pakket @angular/common. Een probleem dat zich voordeed dat was dat het import-statement van dit pakket niet in alle gevallen werd weggehaald. Mijn Angular migratie tool haalt dit statement wel weg als dit kan, maar laat het import- statement staan wanneer er in het component gebruik gemaakt wordt van ingebouwde pipes of attribute directives (zoals ngClass en ngStyle).

Moderne Angular conventie: injects in plaats van constructors

Een relatief nieuwe Angular conventie is om injects te gebruiken in plaats van constructors. In constructors werden voorheen services geïnjecteerd. De officiële Angular documentatie raadt verder aan om de constructors leeg te laten. Overigens kunnen constructors nog steeds gebruikt worden.

Er is recentelijk een schematic toegevoegd om in Angular constructors te converteren in injects, namelijk: ng generate @angular/core:inject

Het voordeel van dit commando is dat dit leidt tot minder regels code. Mijn Angular migratie tool doet hetzelfde, maar laat constructors ongemoeid wanneer er een super() aanroep binnen de constructor staat.

angular constructors to injects

Een grotere rol voor app.config.ts

In eerdere Angular applicaties waren er twee soorten modules, namelijk root- en feature-modules. Voorheen werden de meeste applicatie-instellingen opgenomen in de root-module. Maar omdat modules optioneel zijn, worden nu de applicatie-instellingen opgenomen in het bestand app.config.ts. Net zoals in de root-module is er in app.config.ts een providers-array. Zie afbeelding hier beneden:

Angular app.config.ts version 17 and later

Vanaf Angular 17 zijn er speciale provide-functies, zoals voor de Router, de HttpClient waar interceptors en error-handling in opgenomen kan worden, voor Zone.JS of Zoneless (er is te kiezen voor zowel provideZoneChangeDetection() als provideExperimentalZonelessChangeDetection()). In de code hierboven is ook provideStore() en provideState() opgenomen voor ngRx.

In Angular 19 zijn de zogenaamde initializer-tokens vervangen door een gelijknamige provide-functie. Dit leidt tot schonere code en vereenvoudigt het proces om de applicatie in te stellen. Bovendien zijn de initializer-tokens in Angular 19 deprecated. Zie afbeelding hieronder:

De nieuwe signals

In een eerder blogbericht heb ik geschreven over de nieuwe signals. Decorators zoals: @Input, @ViewChild, @ContentChild, etc. kunnen vervangen worden door gelijknamige signals. In Angular 19 is er een commando om deze decorators te converteren in signals, namelijk: ng g @angular/core:signals

Na het intypen van bovenstaand commando in de terminal verschijnt er een korte vragenlijst met welke signals er gemigreerd moeten worden. Wel is deze migratie conservatief, dit wil zeggen dat wanneer er iets niet gemigreerd kan worden zonder de code te breken, dan blijft alles zoals het is.

Tot slot

Dit blogbericht omvat een aantal zaken waar ik tegenaan ben gelopen tijdens het updaten en upgraden van Angular applicaties. Er is echter nog veel meer dat in een ander blogbericht behandeld zal worden. Zoals: het herschrijven van routes, het repareren van Angular Material SCSS, updaten van deprecated code en het updaten van test-bestanden (de zogenaamde specification-files).

Leave a Reply

*