© Spirit Boom Cat/Shutterstock.com
Erweiterte Aspekte von Server-side Rendering mit Angular

Erinnerungslücken und unheimliche Täler


Beim Einsatz von SSR gilt es, die Unterschiede zwischen Client und Server auszugleichen, bereits abgerufene Daten am Client wiederzuverwenden und Zeiten von Inaktivität zu überbrücken.

Wie in der Ausgabe 6.19 des Windows Developer gezeigt [1], verbessert serverseitiges Rendering (SSR) die wahrgenommene Startperformance: Der Benutzer sieht nämlich erste sinnvolle Informationen bereits nach dem Herunterladen der index.html, die das vorgerenderte Markup enthält. Die Anwendung wird jedoch erst interaktiv, nachdem der Browser auch die JavaScript Bundles geladen hat.

Diese Maßnahme verringert Absprünge und unterstützt die Suchmaschinenoptimierung. Der Kasten „SSR aktivieren“ fasst die wichtigsten Schritte zum Aktivieren von SSR in einer bestehenden Angular-Anwendung zusammen.

SSR aktivieren

Zum Aktivieren von SSR in einer bestehenden Angular-Anwendung sind die folgenden drei Schritte auszuführen:

  • Code für SSR generieren: ng add @nguniversal/express-engine --clientProject flight-app

  • Anwendung für SSR bauen: npm run build:ssr

  • Anwendung mit SSR starten: npm run serve:ssr

Die in Schritt zwei und drei aufgerufenen npm-Skripte werden durch ng add im ersten Schritt eingerichtet.

SSR bringt jedoch auch einige Herausforderungen mit sich. Beispielsweise herrschen am Server andere Bedingungen als am Client vor, und diese gilt es zu kompensieren. Außerdem möchte man verhindern, dass die bereits am Server abgerufenen Daten am Client erneut geladen werden müssen. Genau um solche Themen wird sich dieser Artikel kümmern. Die Beispiele finden sich wie immer in meinem GitHub-Account [2].

Unterschiede zwischen Client und Server

Einige Dinge funktionieren am Server ganz anders als am Client. Beispielsweise sind Cookies oder Umleitungen gänzlich anders zu handhaben. Um diese Unterschiede zu kompensieren, muss die Anwendung wissen, wo sie gerade ausgeführt wird. Aus diesem Grund bietet Angular das Token PLATFORM_ID an. Der daran gebundene Wert gibt Auskunft über den aktuellen Ort der Ausführung (Listing 1).

Listing 1

[…] import { PLATFORM_ID, Inject } from '@angular/core'; import { isPlatformBrowser, isPlatformServer } from '@angular/common'; @Component({ […] }) export class HomeComponent implements OnInit { platform = 'unkown'; constructor( @Inject(PLATFORM_ID) private platformId: Object) { } ngOnInit() { if (isPlatformBrowser(this.platformId)) { this.platform = 'Browser'; } else if (isPlatformServer(this.platformId)) { this.platform = 'Server'; } } }

Damit die Anwendung nicht von konkreten Werten der PLATFORM_ID abhängig ist, wertet sie ihn mit den beiden Hilfsfunktionen isPlatformBrowser und isPlatformServer aus.

Unterschiedliche Services für Client und Server

Der Vorteil der im letzten Abschnitt vorgestellten Lösung ist ihre Einfachheit. Wendet man sie jedoch häufig an, verschlechtern die ständigen Verzweigungen die Codequalität.

In diesen Fällen ist der Entwickler besser beraten, für beide Ausführungsumgebungen einen eigenen Service anzubieten. Diese kapseln die jeweilige Logik und lassen sich auch leichter testen:

export abstract class PlatformService { ... } @Injectable() export class ClientPlatformService implements PlatformService { … } @Injectable() export class ServerPlatformService implements PlatformService { … }

Nun stellt sich die Frage, wie diese Services zu registrieren sind, damit der ClientPlatformService nur bei der Ausführung am Client und der ServerPlatformService lediglich beim serverseitigen Vorrendern zum Einsatz kommen. Eine Antwort liefert die Modulstruktur, die sich beim Einbinden der SSR-Unterstützung ergibt (Abb. 1).

steyer_rauch_ssr_angular_1.tif_fmt1.jpgAbb. 1: Das serverseitige „AppModule“ importiert sein clientseitiges Gegenstück

Der Node.js-basierte Server startet unter Nutzung des Codes in main.server.ts ein serverseitiges AppModule (app.serv...

Neugierig geworden? Wir haben diese Angebote für dich:

Angebote für Gewinner-Teams

Wir bieten Lizenz-Lösungen für Teams jeder Größe: Finden Sie heraus, welche Lösung am besten zu Ihnen passt.

Das Library-Modell:
IP-Zugang

Das Company-Modell:
Domain-Zugang