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 letzten Ausgabe des Windows Developer gezeigt, 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.
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).
[…] 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.