Angular 13 ist da!
03.11.2021
Noch vor dem Jahresende erschien Anfang November 2021 die neue Major-Version 13 von Angular. Auch diese Version bringt keine großen Änderungen an der Oberfläche des Frameworks mit, sondern verbessert vor allem Details im Hintergrund. Es gibt ein paar wenige Breaking Changes, die aber für die meisten Entwicklerinnen und Entwickler nicht interessant sein dürften.
Wir stellen in diesem Blogpost wie immer die wichtigsten Neuigkeiten vor. Den Code des Beispielprojekts BookMonkey aus dem Angular-Buch halten wir stets auf GitHub aktuell.
Die offizielle Mitteilung zum neuen Release finden Sie im englischsprachigen Angular-Blog. Im Changelog von Angular und der Angular CLI finden Sie außerdem alle Details zum neuen Release.
Die Update-Infos für neuere Versionen von Angular finden Sie in separaten Blogartikeln. Wenn Sie das Update durchführen möchten, lesen Sie bitte alle Artikel in der gegebenen Reihenfolge.
Projekt updaten
Wenn Sie Ihr bestehendes Projekt aktualisieren möchten, folgen Sie bitte den Instruktionen im Angular Update Guide.
Mithilfe des Befehls ng update
erhalten Sie außerdem Infos zu möglichen Updates direkt im Projekt.
# Projekt auf Angular 13 aktualisieren
npx @angular/cli@13 update @angular/core@13 @angular/cli@13
Bitte beachten Sie, dass es noch einige Zeit dauern kann, bis Community-Projekte wie NgRx oder Nrwl Nx ebenso mit Angular 13 kompatibel sind.
Neue Versionen: Node.js, TypeScript und RxJS
Angular 13 benötigt die folgenden Versionen von Node.js, TypeScript und RxJS:
- Node.js: mindestens Version 12.20.0. Außerdem wird jetzt auch Node 16 unterstützt.
- TypeScript: mindestens Version 4.4.2. Ältere Versionen werden nicht mehr unterstützt.
- RxJS: Bei neu angelegten Angular-Projekten wird jetzt die Bibliothek RxJS in der aktuellen Version 7 genutzt. RxJS 6 wird weiterhin unterstützt. Bei bestehenden Projekten wird die Versionsnummer nicht automatisch erhöht.
Test Module Teardown
Schon mit Angular 12.1 wurde das sogenannte Test Module Teardown eingeführt. Mit Angular 13 ist das Teardown nun automatisch aktiv, siehe Commit.
Diese Option, die bisher freiwillig aktiviert werden konnte, sorgt dafür, dass beim Unit-Testing mit dem TestBed
das erzeugte Modul nach dem Test wieder zerstört wird. Dabei wird z. B. das DOM-Element der erzeugten Komponente wieder entfernt.
Die Option destroyAfterEach
kann für jeden Test separat aktiviert werden:
TestBed.configureTestingModule({
teardown: { destroyAfterEach: true },
// ...
});
Alternativ ist auch eine globale Einstellung in der Datei test.ts
möglich.
Für neue Projekte mit Angular 13 ist das Test Module Teardown per default eingeschaltet.
Für existierende Apps wird das Teardown zunächst explizit deaktiviert, sodass keine Anpassungen im Code notwendig sind.
Für weitere Informationen empfehlen wir den Blogpost von Lars Gyrup Brink Nielsen.
Vereinfachte Schnittstelle für Dynamic Components
Mit der Schnittstelle der Klasse ViewContainerRef
können Komponenteninstanzen dynamisch zur Laufzeit der Anwendung erzeugt werden.
Dafür war es bisher notwendig, den ComponentFactoryResolver
zu verwenden, um zunächst eine Factory für die jeweilige Komponente zu erstellen. Das war aufwendig und erzeugte viel Code.
Die Schnittstelle für die Methode createComponent()
wurde mit Angular 13 vereinfacht, siehe Commit.
Jetzt ist es möglich, direkt eine Komponentenklasse zu übergeben, die dann in einem ViewContainer gerendert wird.
Das folgende Beispiel zeigt (stark vereinfacht!), wie eine Komponente dynamisch im ViewContainer einer Direktive erstellt werden kann:
import { ViewContainerRef } from '@angular/core';
import { MyComponent } from './my.component';
@Directive({ /* ... */ })
export class MyDirective {
constructor(private vcr: ViewContainerRef) {
this.vcr.createComponent(MyComponent);
}
}
Zusammen mit Dynamic Imports kann die betreffende Komponente sogar "lazy" geladen werden.
Sie wird in ein eigenes Bundle verpackt und erst beim Aufruf von import()
tatsächlich heruntergeladen.
Es ist damit nun noch einfacher, einzelne Komponenten auszulagern separat bereitzustellen.
import('./my.component').then(m => {
this.vcr.createComponent(m.MyComponent);
});
Persistent Cache
In Projekten mit Angular 13 ist der neue Persistent Disk Cache automatisch aktiv.
Dabei werden Teile der gebauten Anwendung zwischengespeichert, um zukünftige Builds zu beschleunigen.
Der Cache kann über die angular.json
konfiguriert werden:
{
// ...
"cli": {
"cache": {
"enabled": true
}
}
}
Informationen zur Konfiguration des Build Cache finden Sie in der Angular-Dokumentation.
Support für IE11 eingestellt
Die Unterstützung für den Internet Explorer 11 wurde entfernt. Nachdem in der letzen Version der Support bereits "deprecated" wurde, ist Angular jetzt offiziell nicht mehr im Internet Explorer lauffähig.
Bei der Migration zu Angular 13 werden deshalb einige Einträge aus der polyfills.ts
entfernt.
Außerdem ist Differential Loading, das mit Angular 8 eingeführt wurde, nicht mehr notwendig. Dabei wurden für ältere Browser separate Bundles in ES5 gebaut. Da alle aktuellen Browser auch modernere Varianten von JavaScript unterstützen, wird Differential Loading nicht mehr genutzt.
Bibliotheken mit Ivy-Compilation
Nachdem der neue Renderer Ivy eingeführt wurde, musste die Kompatibilität mit Anwendungen gewährt werden, die noch auf die veraltete View Engine setzten.
Dafür wurde der Angular Compatibility Compiler (ngcc
) entwickelt: Alle Bibliotheken, die auf NPM veröffentlicht werden, mussten zunächst weiterhin mit der View Engine kompiliert werden. Beim Build einer Ivy-Anwendung wurde automatisch der ngcc
aktiv, um die Anweisungen in Ivy-Instruktionen zu übersetzen.
Dieser Prozess braucht Zeit.
Möglicherweise haben Sie diese Ausgabe beim ng serve
schon einmal gesehen – sie stammt vom ngcc
:
Compiling @angular/core : es2015 as esm2015
Compiling @angular/common : es2015 as esm2015
Compiling @angular/platform-browser : es2015 as esm2015
Compiling @angular/common/http : es2015 as esm2015
Seit Angular 13 können Bibliotheken direkt in Ivy-Instruktionen kompiliert und veröffentlicht werden.
Der Code ist dann nicht mehr mit der View Engine kompatibel.
Der ngcc
wird damit weiter an Bedeutung verlieren und künftig entfernt werden können.
Die View Engine wird seit Angular 13 nicht mehr unterstützt.
Mehr Infos zum Veröffentlichen von Bibliotheken mit Ivy finden Sie in der Angular-Dokumentation.
Neue Methoden für Reactive Forms
Für die Formularverarbeitung mit Reactive Forms wurden neue Methoden hinzugefügt, siehe Commit:
hasValidator
,hasAsyncValidator
addValidators
,addAsyncValidators
removeValidators
,removeAsyncValidators
Damit ist es möglich, programmatisch zu prüfen, ob ein bestimmter Validator auf einem Control vorhanden ist, um z. B. Required-Felder optisch zu markieren. Außerdem können einzelne Validatoren dynamisch hinzugefügt oder entfernt werden. Das kann z. B. in Abhängigkeit von anderen Formularwerten implementiert werden. Bisher war es nur möglich, alle Validatoren eines Controls zu setzen oder zu entfernen.
// prüfen, ob required-Validator auf dem Control vorhanden ist
isRequired(controlName: string) {
const control = this.form.get(controlName);
return !!control && control.hasValidator(Validators.required)
}
// required-Validator dynamisch hinzufügen
addRequired(controlName: string) {
const control = this.form.get(controlName)!;
control.addValidators(Validators.required);
control.updateValueAndValidity();
}
Wir haben ein funktionierendes Beispiel auf GitHub bereitgestellt.
Auch die Typisierung bei den Formularen hat sich verbessert. Es wurde ein neuer Typ FormControlStatus
eingeführt, welcher nun bei form.status
und form.statusChanges
zum Einsatz kommt, siehe Commit:
export type FormControlStatus = 'VALID'|'INVALID'|'PENDING'|'DISABLED';
Sonstiges
- $localize stable: Die Funktion
$localize
zur Übersetzung von Texten in der Anwendung gilt jetzt als stable. Siehe auch dieser Beitrag im Angular-Blog: Angular localization with Ivy. - deployUrl: Die Option
deployUrl
fürng build
ist nun deprecated. Falls Sie ein ähnliches Verhalten wiederherstellen möchten, eignet sich eine Kombination aus dem ParameterbaseHref
und dem InjectionTokenAPP_BASE_HREF
. - Event für routerLinkActive: Die Direktive
routerLinkActive
emittiert das EventisActiveChange
, wenn sich der Aktivitätsstatus dieses Links ändert. Das kann man nutzen, um weitere Aktionen anzustoßen, wenn ein RouterLink aktiviert oder deaktiviert wird, siehe Commit. - Adobe Fonts Inlining: Fonts Inlining wurde bisher "out of the box" für Google Fonts unterstützt. Dabei werden beim Build die Font-Dateien heruntergeladen und zusammen mit der gebauten Anwendung abgelegt. Dieses Verfahren wird jetzt auch für Adobe Fonts unterstützt.
- loadChildren String Syntax: Die veraltete String-Syntax für Lazy-Loading mit
loadChildren
wurde entfernt. Die alte Schreibweise ist seit Angular 9 deprecated und sollte ohnehin nicht mehr genutzt werden. - Zeitzone für DatePipe: Die
DatePipe
nutzt ein neues InjectionTokenDATE_PIPE_DEFAULT_TIMEZONE
, mit dem die Zeitzone eingestellt werden kann, siehe Commit. - min/max-Validatoren mit
null
: Bei Template-Driven Forms können die Validatoren fürmin
undmax
nun auch den Eingabewertnull
verarbeiten. Der Validator wird dadurch deaktiviert. Ein ähnliches Verhalten wird bereits vonminLength
undmaxLength
unterstützt. Siehe Commit. - renderModuleFactory entfernt: Die Funktion
renderModuleFactory
, die im Zusammenhang mit Server-Side Rendering relevant ist, steht nicht mehr zur Verfügung. Stattdessen soll die FunktionrenderModule
genutzt werden.
Es hat sich also einiges getan, und es wurden viele Punkte aus der Sektion "In progress" von der Roadmap (Stand: 19.05.2021) abgearbeitet. Als einer der wichtigsten offenen Punkte sind nun noch die optionalen NgModules zu sehen, für die es jüngst eine Befragung der Community gab (siehe RFC). Die Roadmap für die zukünftige Entwicklung von Angular wird regelmäßig in der Dokumentation veröffentlicht: https://angular.io/guide/roadmap.
Wir wünschen Ihnen viel Spaß mit Angular 13! Haben Sie Fragen zur neuen Version, zum Update oder zu Angular? Schreiben Sie uns!
Viel Spaß wünschen Danny, Ferdinand und Johannes
Titelbild: Blick vom Poon Hill, Nepal, 2018. Foto von Ferdinand Malcher
Suggestions? Feedback? Bugs? Please fork/edit this page on Github.