Zum Inhalt springen

Angular macht sich bereit für die Zukunft – neue Konzepte für ng16 im Überblick

Es tut sich in letzter Zeit einiges bei Angular, einen der großen Player für Single-Page-Anwendungen. Neuerdings gibt es neben Standalone Components auch das neue Konzept Signals, unter Anderem bekannt durch SolidJS. Dieses neue Pattern bietet Entwicklern leistungsstarke Funktionen, um die Anwendungsleistung zu optimieren und Frachter wie zone.js loszuwerden!
In diesem Artikel werfen wir einen Blick auf Signals in Angular und deren Einsatzmöglichkeiten zur effizienten Change-Detection und Kommunikation in Komponenten.

Die moderne Angular Komponente

Obwohl es nicht das beliebteste Framework unter SPA-Bibliotheken ist, trotzt Angular mit seiner Stabilität den sich immer verändernden Bedingungen in der Webwelt. Dabei ist Angular auch des Öfteren Vorreiter. Gerade die Adaption von TypeScript war damals ein richtiger Schritt, dem viele weiteren Bibliotheken folgten.

Standalone Components

Mit Angular 16 gibt es inzwischen viele Features, die Angular auch noch in der Zukunft im Rennen halten werden. Die erste entscheidende Veränderung ist die Möglichkeit seit v14 Standalone Components zu schreiben.
Dies soll dahin führen, dass Komponenten viel mehr Selbstbeschreibung bekommen, und nicht immer über ein Modul versorgt werden müssen. Dabei ist es möglich inkrementell auf Standalone Components umzustellen. Die Mindestausprägung einer Component sieht folgendermaßen aus:

import { Component } from '@angular/core';

@Component({
  selector: 'my-test',
  standalone: true,
  template: 'hello world',
})
export class myTestComponent {}

Wichtig hierbei, ist das neue Property standalone: true, welches ein Komponente genau zu dieser alleinstehenden Komponente macht.

Will eine andere Angular-Component nun diese Komponente nutzen, wird in der Component-Declaration das Property imports genutzt:

@Component({
  selector: 'my-app',
  standalone: true,
  imports: [CommonModule, myTestComponent],
  template: `
    <h1>Hello from {{name}}!</h1>
    <a target="_blank" href="https://angular.io/start">
      Learn more about Angular 
    </a>
    <my-test/>
  `,
})
export class App {
  name = 'Angular';
}

bootstrapApplication(App);

Hier bereits sichbar am Beispiel CommonModule, müssen alle Abhängigkeiten innerhalb der Komponente über das imports-Array abgefrühstückt werden. Dabei ist das CommonModule für Grundfunktionalitäten im Angular Templating zuständig.

Signals – fine grained Reactivity

Dieses Konzept hat mich als Entwickler bereits in SolidJS begeistert. Fine grained Reactivity bedeutet, dass es weniger Magie im DOM benötigt um reaktive Inhalte zu schreiben. Genau dafür sind Signals da. Letztendlich ist ein Signal „nur“ ein Object mit Funktionen. Dieses Signal kann aber sehr dediziert Änderungen und Abhängigkeiten in anderen Signals verwalten. Ein Signal lässt sich relativ leicht in Angular initialisieren:

@Component({
  standalone: true,
  selector: 'my-test',
  template: '',
})
export class MyTestComponent {
  public test = signal([]);
}

Mit diesem neuen State-System kann Angular leichter darüber entscheiden, wann welche Komponenten eine Change detection anstoßen müssen. Bei der OnPush-Strategie funktionierte das ganze über zone.js und das Referenz-System in JavaScript. Signals machen also auch die OnPush Strategie etwas erwachsener.

Wenn wir ein schreibbares Signal updaten wollen, und damit auch abhängige Komponenten-Teile benachrichtigen, machen wir das mit .set oder für einen computed Value mit .update. Das Ganze sieht dann so aus:

import { CommonModule } from '@angular/common';
import { Component, signal } from '@angular/core';

@Component({
  standalone: true,
  selector: 'my-test',
  imports: [CommonModule],
  template: `
  <p><button (click)="doUpdate()" >update test</button></p>
  <p>{{test()}}</p>
  `,
})
export class MyTestComponent {
  public test = signal<number[]>([]);

  doUpdate() {
    this.test.set([1, 2, 3]);
  }
}

Mit dem Besagten computed Value können wir dementsprechend Werte mit anderen Logiken kombinieren oder in der Berechnung auf die aktuellen Werte zugreifen:

import { CommonModule } from '@angular/common';
import { Component, signal } from '@angular/core';

@Component({
  standalone: true,
  selector: 'my-test',
  imports: [CommonModule],
  template: `
  <p><button (click)="doUpdate()" >update test</button></p>
  <p>{{test()}}</p>
  `,
})
export class MyTestComponent {
  public test = signal<number[]>([1, 2, 3]);

  doUpdate() {
    this.test.update((current) => current.map((el) => el + 1));
  }
}

Aber auch Seiteneffekte lassen sich über Signals realisieren. Und das Beste daran – ohne komplizierten RxJs-Streams oder Ähnlichem. Beispiele für Anwendungsfälle sind z.B Logging oder Data-Analytics. Dafür gibt es eine sog. effect Funktion in Angular Komponenten:

@Component({...})
export class EffectiveCounterCmp {
  readonly count = signal(0);
  
  private loggingEffect = effect(() => {
    console.log(`The count is: ${this.count()})`);
  });
}

Angular goes React?

Tatsächlich erinnern Teilstrukturen wie Effects an das Konzept React-Hooks vermischt mit dem Signals Konzept von SolidJs. Auch die Standalone Components nähern sich dem Konzept einer selbstbeschreibenden Komponente an, was man eher aus React kennt. Ist das Ganze allerdings schlecht?

Ich persönlich finde diese Änderungen sind ein wichtiger Schritt in die Nachhaltigkeit des Frameworks Angular. Der unique selling point von Angular war gegenüber der Konkurrenten immer schon ein „batteries included“ Tool. Sachen wie Observables und rxJs haben aber die Lernkurve etwas steiler gemacht. Dort können Signals durchaus viel Abhilfe bieten.
Die Adaption von bewährten Architekturkonzepten tut ng meiner Meinung nach sehr gut. Es fühlt sich natürlich an diese Adaptionen zu nutzen und es kompromittiert trotzdem nichts von den Funktionalitäten des Enterprise-SPA-Frameworks. Ich hoffe auf weitere Schritte in diesem Stil und bin gespannt auf das was noch kommt!

Habe ich Ihr Interesse geweckt?
Kontaktieren Sie mich!

Gerne liefere ich Ihnen ein unverbindliches Angebot zu Ihrer Idee!

info@slezak-it.de