Neu in Angular 5

Angular 5 ist da – das sind die neuen Features!
Kommentare

Angular 5 ist erschienen. Die fünfte Auflage des JavaScript-Frameworks von Google bringt zahlreiche Neuerungen und Optimierungen mit. Wir schauen uns die neuen Features im Detail an und geben einen Ausblick auf Angular 6.

War noch das Update von AngularJS auf Angular Version 2 ein riesiger Sprung, brachte die Version 4 zwar einige neue Features, blieb aber im Wesentlichen abwärtskompatibel (siehe auch: Angular 4 – das Update: Diese Features müssen Sie kennen). Nach nunmehr guten sechs Monaten ist die nächste Major-Version von Angular verfügbar.

Das Update auf Angular 5 ist, wie bereits Angular 4, eher inkrementell, da die meisten Änderungen unter der Haube erfolgt sind. Allerdings sind nun definitiv einige Breaking Changes enthalten, und somit kommt auf einige Entwickler etwas Arbeit zu. Allen Entwicklern, die ihre Codebasis im Verlauf der letzten Angular-Versionen auf dem aktuellsten Stand gehalten haben, werden die Umstellungen auch diesmal leicht fallen.

Der Fokus von Angular 5 lag darauf, Angular noch schneller zu machen: Sowohl die Ladezeit soll durch kleinere Bundles verbessert worden sein, als auch die Ausführung durch Optimierungen am Compiler. Für manche Projekte ist auch wichtig zu sehen, dass an ng-upgrade weitergearbeitet wird. Damit lassen sich AngularJS-Anwendungen sanft auf Angular migrieren, und auch umgekehrt Angular-Komponenten als “Downgrade” in AngularJS-Anwendungen einbetten. Kleinere Verbesserungen können auch großen Einfluss haben, so unterstützen die Material-Design-Komponenten nun auch serverseitiges Rendering mit Angular Universal.

Neu ist ebenfalls das auf der Angular-Mix-Konferenz angekündigte Angular Labs. Experimentelle Technologien und Features werden in einem speziellen Labs-Bereich außerhalb des Angular Frameworks entwickelt und können frühzeitig durch Entwickler begutachtet und getestet werden, ohne negativen Einfluss auf die Releaseplanung des Frameworks zu nehmen.

TypeScript 2.4 Support in Angular 5

Nachdem mit Angular 4 die Verwendung von TypeScript in Version 2.3 ermöglicht wurde (inklusive der Strict-Null-Checks-Option vollständig und fehlerfrei seit Version 4.3), wird mit Angular 5 jetzt auch offiziell die TypeScript-Version 2.4 unterstützt. Im Folgenden werden die wesentlichen Features der neueren TypeScript-Version beschrieben.

Ein neues Feature, welches mit Version 2.4 in TypeScript landet, sind String-basierte Enums. Dies bedeutet, dass die Member eines Enum nun statt mit einer Zahl auch mit einem String belegt werden können:

 

enum Colors {
Red = "RED",
Green = "GREEN",
Blue = "BLUE",
}

Es sollte hierbei beachtet werden, dass String-Enums nicht wie ihre zahlenbasierten Geschwister rückwärts gemappt werden können. Eine Abfrage wie Colors[„RED“] ist also nicht möglich, um an den String „Red“ zu gelangen.

Weiterhin wird in der neueren TypeScript-Version das Type-Checking in Bezug auf Generics verbessert. Zum einen wird das Type-Checking allgemein strikter, zum anderen können nun auch die Rückgabetypen generischer Funktionen inferiert werden, sodass beispielsweise folgender Aufruf zu einem Fehler führt:

  
let foo: Promise<number> = new Promise(resolve => {
    resolve("bar");
    // Error
});

Eine weitere Verbesserung ist die sogenannte Weak-Type-Detection: Weak Types (schwache Typen) können jetzt erkannt werden. Ein Typ ist genau dann ein schwacher Typ, wenn er nur optionale Parameter hat, wie zum Beispiel der folgende Typ:

  
export interface Options {
  showSideNav?: boolean;
  description?: string;
}


Wird nun versucht, ein Objekt, das keine gemeinsamen Properties besitzt, einem solchen schwachen Typen zuzuweisen, so ist dies ein Compiler-Fehler, wie im folgenden Code-Beispiel zu sehen:

  

function checkOptions(opts: Options) {
  // ...
}

const foo = { showMenu: true };

// Error
checkOpts(foo);

// Works
checkOpts(foo as Options);

Progressive Web Applications

Aktuell ist die Entwicklung von PWAs (Progressive Web Applications) ein komplexer und aufwendiger Prozess. Nicht nur bei der Entwicklung gilt es, Besonderheiten zu beachten, auch beim Deployment muss darauf geachtet werden, dass es weder zu einer Beeinträchtigung des Caching, noch zur Auslieferung älterer Versionen kommt. Mit Angular 5 soll sich dies ändern: Die Entwicklung von PWAs soll so weit vereinfacht werden, dass diese sogar standardmäßig erstellt werden können und damit Nutzer wie Entwickler gleichermaßen profitieren.

Angular bringt mit Angular-CLI die Möglichkeit mit, von Haus aus Konfiguration und Code zu erzeugen. Das soll perspektivisch das Erstellen mobiler Webanwendungen erlauben, die Features von nativen mobilen Anwendungen mitbringen: Offlinefähigkeit, Push-Benachrichtigungen und ein Anwendungs-Logo im Startmenü der jeweiligen Plattform. Unter der Haube werden dafür Serviceworker verwendet, mit denen die Offlinefähigkeit der Anwendung selbst und Behandlung von Push-Benachrichtigungen implementiert werden können. Angular stellt Serviceworker über das Modul @angular/service-worker bereit. Weitere benötigte Elemente sind die Erstellung des HTML5-Caching-Manifests und die Erzeugung einer Application-Shell. Innerhalb der Anwendung muss ggf. auf Routing-Events unter Berücksichtigung des Verbindungszustands (offline/online) reagiert werden.

Aktiviert wird die Unterstützung für PWAs durch folgendes Kommando:

ng set apps.0.serviceWorker=true

Build

Schon für progressive Web Applications reichen Updates im Framework alleine nicht, das Build-Tooling muss erweitert werden. Genau das geschieht bei Angular-CLI auch in anderen Bereichen: Die statische Analyse, die im AOT-Modus (Ahead of Time Compilation) geschieht, wird auch teilweise schon im normalen Build durchgeführt. Damit werden viele Fehler bereits zur Build-Zeit, statt erst zur Laufzeit, erkannt. Auch am Tree-Shaking wurde weiter gearbeitet, um dadurch die Größe der erzeugten Anwendung weiter zu reduzieren. Dazu wurde zum einen der AOT-Modus beschleunigt, zum anderen unterstützt er nun auch inkrementelle Builds, was die Build-Zeit weiter deutlich reduziert.

API Summit 2017

Web APIs mit moderner Web-Technologie konsumieren

mit Rainer Stropek (software architects)

API First mit Swagger & Co.

mit Thilo Frotscher (Freiberufler)

Für schnellere Builds kann bazel, ein Build-Werkzeug von Google, integriert werden. Derzeit ist dies jedoch noch in einem sehr frühen Stadium. Auch der von Google bekannte Closure Compiler soll zukünftig stärker genutzt werden, um besser optimierte Buildergebnisse zu erzielen.

Formulare

Zur Performanceverbesserung kann an Formularen nun spezifiziert werden, wann Validatoren ausgeführt werden sollen. Bisher war es so, dass bei jeder Änderung eines FormControl-Wertes die Validierung durchgeführt wurde – potentiell also bei jedem Tastenanschlag. Bei komplexeren Validierungen kann dadurch die Performance spürbar leiden. Mit Angular 5 kann durch die neue updateOn-Option genauer spezifiziert werden, wann Angular Validierungen durchführen soll. Zur Auswahl stehen ‚change‘, womit das bisherige Verhalten spezifiziert wird, ’submit‘ und ‚blur‘.

Verwendung mit Reactive Forms

In Reactive-Forms wird das updateOn-Property bei der Instantiierung des FormControl im Parameterobjekt mitgegeben. Beispiel für ein FormControl mit entsprechendem Parameterobjekt:

  
this.email = new FormControl(null, { updateOn: 'blur' });

Sollen auch Validatoren spezifiziert werden, werden diese ebenfalls als Property des Parameterobjekts spezifiziert:

  this.email = new FormControl(null, {
  validators: Validators.required,
  updateOn: 'blur'
});

Statt auf dem jeweiligen FormControl kann über FormGroup und FormArray das Verhalten für alle Unterelemente spezifiziert werden. Beispiel einer FormGroup, die für alle enthaltenen Elemente Validierung zum ’submit‘-Zeitpunkt vorgibt:

  
this.login = new FormGroup({
  email: new FormControl(),
  password: new FormControl()
}, { updateOn: 'submit' });

Die enthaltenen Elemente können dieses Verhalten ihrerseits übersteuern, wie im folgenden Beispiel gezeigt:

  
this.login = new FormGroup({
  email: new FormControl(null, {
     validators: Validators.required,
     updateOn: 'blur'
  }),
  password: new FormControl(null, [Validators.required])
}, {updateOn: 'submit'})

Verwendung mit Template-basierten Formularen

Bei über das Template definierten Formularen kann der mit Angular 5 eingeführte updateOn-Parameter ebenfalls spezifiziert werden. Dies geschieht dann an den ngModelOptions, wie im folgenden Beispiel zu sehen:

  
<input type="email" ngModel [ngModelOptions]="{updateOn: 'submit'}">

Auch hier vererbt sich die Einstellung entsprechend der Elementschachtelung im DOM. Im folgenden Beispiel wird die Einstellung direkt am Formular-Element vorgenommen:

  


<form [ngFormOptions]="{updateOn: 'submit'}">
 <input name="email" ngModel type="email">
 <input name="password" ngModel type="email">
</form>


Genauso wie bei den reactive Forms kann ein untergeordnetes Element die vorgenommene Vorgabe ueberschreiben:

  


<form [ngFormOptions]="{updateOn: 'submit'}">
 <input name="email" ngModel type="email" [ngModelOptions]="{updateOn: 'blur'}">
 <input name="password" ngModel type="email">
</form>



HttpClient

Der mit Angular 4.3 eingeführte HttpClient unterstützt für Header und Parameter jetzt ein Parameter-Objekt. Damit lässt sich eine Menge Tipparbeit sparen, wie hier zu sehen:

  
http.get("/api", {
    headers: {
        "X-DEMO-HEADER": "demo"
    },
    params: {
        "foo":  "bar"
    },
})

I18N Pipes

Die i18n Pipes (date, number, currency, percent) sind von mehreren Änderungen aufgrund interner Umbauten betroffen. Dazu gehört, dass das bisher von Angular genutzte Intl-API aufgrund von Browserinkonsistenzen nicht mehr genutzt wird. Stattdessen wurde zur Lokalisierung auf einen Export von Daten aus dem Unicode Common Locale Data Repository (CLDR) gesetzt. Diese Änderungen stellen einen API-Bruch dar: Es wird nun standardmäßig nur die US-Englische Locale “en-US” aktiviert. Will man eine andere Locale nutzen, muss man diese erst importieren. Zum Importieren der deutschen Locale “de” (entspricht “de-DE” im Intl-API) ist folgender Code, beispielsweise im AppModule, nötig:

  
import { registerLocaleData } from '@angular/common';
import localeDe from '@angular/common/locales/de';

registerLocaleData(localeDe);

Die so importierte Locale kann nun wie gehabt verwendet werden:

  

@NgModule({
  // ...
  providers: [{provide: LOCALE_ID, useValue: 'de'}]
})
export class AppModule{}

Falls man aus irgendeinem Grund auf die bisherigen Intl-Pipes angewiesen ist, kann man diese (vermutlich noch bis zur nächsten Angular-Major-Version) explizit spezifizieren. Dafür muss allerdings das alte Intl-API-Polyfill und das DeprecatedI18NPipesModule importiert werden:

  
import { NgModule } from '@angular/core';
import { CommonModule, DeprecatedI18NPipesModule } from '@angular/common';

@NgModule({
  imports: [
    CommonModule,
    // Deprecated Modul nach CommonModule importieren
    DeprecatedI18NPipesModule
  ]
})
export class AppModule { }

Zusätzlich zu der neuen Art, Locales bereitzustellen, wird zu jeder Pipe auch ein neuer (optionaler) Parameter hinzugefügt. Mit diesem kann man die zu verwendende LOCALE_ID auch für jede Pipe einzeln setzen.

In den einzelnen Pipes ergeben sich ebenfalls API-Brüche, die sich aber meist auf neue Standardwerte von Pipe-Parametern beschränken (etwa die Anzahl an Stellen nach dem Komma bei der Percent-Pipe oder das Währungssymbol bei der Currency-Pipe). Diese Änderungen sind im Detail im Angular-Changelog beschrieben.

Router

Der Angular Router wurde um zusätzliche Events erweitert. Damit lassen sich jetzt beispielsweise Fortschrittsanzeigen umsetzen, die bei einem Route-Wechsel angezeigt werden. Die Events dazu sind ActivationStart und ActivationEnd bzw. ChildActivationStart und ChildActivationEnd.

Die Umsetzung eines Spinners könnte beispielsweise so aussehen:

  
router.events
    // Event = RouteEvent | RouterEvent
    .filter(e => e instanceof RouteEvent)
    .subscribe(e => {
        if (e instanceof ActivationStart) {
            spinner.start();
        } else if (e instanceof ActivationEnd) {
            spinner.end()
        }
    });

Animationen

Das Animationen-Paket von Angular 5 wurde um etwas Syntax-Zucker erweitert. So lässt sich jetzt auf numerische Wertänderungen durch :increment und :decrement reagieren, um entsprechende Transitionen zu animieren. Die Verwendung illustriert das folgende Beispiel:

  @Component({
    animations: [
        trigger("counter", [ 
            transition(':increment', [ /*...*/ ]),
            transition(':decrement', [ /*...*/ ]),
        ])
    ],
    template: `
    <span [@counter]="count">
    `
})
class MyComponent() { 
    count = 1;
}

Animationen lassen sich in Angular 5 nun auch über per Data-Binding verbundene Werte aktivieren und deaktivieren. Dazu wird das .disabled Property des Trigger-Wertes gebunden. Das folgende Beispiel zeigt die Verwendung:

  @Component({
    animations: [
        trigger("val", [ /* ... */])
    ],
    template: `
    


<div [@val]="prop" [@val.disabled]="animationDisabled">
    `
})
class MyComponent() { 
    prop = '';
    animationDisabled = false;
}

Bisher wurde bei der Animation von untergeordneten Elementen lediglich unterstützt, die Auswahl auf eine bestimmte Anzahl zu beschränken, die von vorne gezählt wurde. Nun werden auch negative Limits unterstützt, die sich damit auf die letzten-x Elemente beziehen. Beispiel für die letzten 5 Elemente mit der Klasse person:

trigger("anim", [
    transition(":enter", [
        query(
            ".person", 
            [ /** ... **/ ],
            { limit: -5 }
        )
    ])
])

Breaking Changes in Angular 5

Folgende APIs wurden bereits in Angular 4 als “deprecated” markiert und sind in Angular 5 entfernt worden:

  • Das OpaqueToken wurde entfernt, stattdessen ist jetzt InjectionToken zu verwenden
  • Der Konstruktor-Parameter des ErrorHandler wurde entfernt.
  • Von NgTemplateOutlet wurde ngOutletContext entfernt.
  • Der Angular Router nimmt als Werte für den Parameter initialNavigation nur noch “enabled” und “disabled”. Die Werte “true”, “false”, “legacy_enabled” und “legacy_disabled” werden nicht mehr akzeptiert.
  • Statt i18n-Kommentaren muss nun das ng-container-Element verwendet werden.
  • Der Compiler nutzt nun standardmäßig nicht mehr enableLegacyTemplate, da das <template>-Element in Angular 4 deprecated wurde, stattdessen soll <ng-template> verwendet werden. Das <template>-Element und die Option enableLegacyTemplate werden in Angular 6 entfernt.
  • Zugunsten des neuen Moduls @angular/common/http ist das Modul angular/http als deprecated markiert worden.
  • Der ReflectiveInjector für Dependency-Injection ist nun deprecated, stattdessen wird nun der StaticInjector verwendet. Dort, wo vorher ReflectiveInjector.resolveAndCreate aufgerufen wurde, muss nun Injector.create verwendet werden.

Die Änderungen können, je nach Projekt, zu einem gewissen Aufwand führen. Generell ist jedoch davon auszugehen, dass ein Upgrade auf Angular 5 keinen unverhältnismäßig hohen Aufwand produzieren dürfte.

Ausblick auf Angular 6

Die nächste Angular Major-Version ist für März oder April 2018 geplant und soll die Version 6 des Framework werden. Auch wenn die genauen Features noch nicht feststehen, so hat sich das Angular-Team zum Fokus der Version bereits geäußert: Anwendungen sollen noch schneller zur Laufzeit und kompakter in der Auslieferung werden. Möglicherweise sind bis dahin auch Experimente aus den Angular-Labs stabil und fließen in das Framework oder AngularCLI ein. Bis dahin lohnt sich auf jeden Fall jetzt schon der Umstieg auf Angular 5!

Unsere Redaktion empfiehlt:

Relevante Beiträge

Meinungen zu diesem Beitrag

X
- Gib Deinen Standort ein -
- or -