Angular SSR für eine E-Commerce Anwendung

Entwicklung des aXpel Shops

In diesem Post beschreibe ich meine Erfahrungen bei der Entwicklung des aXpel Shops mit Angular SSR (Server Side Rendering). Im Wesentlichen wird darauf eingegangen, wie mit Angular SSR sehr schnelle Seitenaufrufe erreicht werden können, die im E-Commerce und für die Search Engine-Optimierung (SEO) eine wichtige Rolle spielen.

Autor: Roberto De Simone
Datum: 21.07.2024
Aktualisiert: 03.11.2024

Bild das blitzschnelle Geschwindigkeit in einer futuristischen Welt symbolisieren soll

Bild “Blitzschnell” mit DALL-E 3 erstellt

Auf dieser Seite

Warum Angular SSR

Angular ist vor allem als JavaScript Framework bekannt, um Web Apps zu erstellen. Web Apps sind interaktive Webseiten, die einen hohen Grad an JavaScript benötigen, um Problemstellungen lösen zu können. Bei Web Apps spricht man auch von “Single Page Applications” (SPA). Bei solchen wird beim Aufruf des URLs die gesamte Anwendung als JavaScript Bundle vom Server an den Browser übermittelt. Die Seite wird danach im Browser aufgebaut - aus dem JavaScript Bundle wird HTML erstellt. Der Aufruf der ersten Seite dauert somit etwas länger, danach ist eine gut entwickelte Angular-Anwendung blitzschnell und bietet eine sehr gute Benutzererfahrung. Bei Single Page Anwendungen spielt die Search Engine Optimierung (SEO) in der Regel keine Rolle.

Möchte man nun aber eine Webanwendung mit Angular entwickeln, bei welcher SEO eine zentrale Rolle spielt, so kommt Angular SSR ins Spiel.

Bei Angular SSR wird beim Aufruf eines URLs die Seite zuerst auf dem Server aufgebaut (gerendert). Das JavaScript, welches bei einer SPA im Browser ausgeführt wird, wird auf dem Server ausgeführt und so die Seite auf dem Server erstellt. Die Seite wird danach zusammen mit dem JavaScript Bundle an den Browser übermittelt. Im Browser wird das JavaScript Bundle erneut ausgeführt und die Seite somit ein zweites Mal erstellt. Diesen Prozess nennt man Hydration (auf die Problematik dieses Prozesses wird im Folgenden immer wieder eingegangen). In der Vergangenheit wurde beim Hydratationsprozess der DOM im Browser vollständig gelöscht und danach neu aufgebaut. Seit Angular 16 werden Teile des DOMs beibehalten, wenn der Server Code und Browser Code das identische Resultat erzeugen. Dieser Prozess (Partial Hydration) wird mit neuen Angular-Versionen nun stetig verbessert, was positive Auswirkungen auf die Core Web Vitals-Werte hat (mehr dazu im nächsten Abschnitt).

Das Rendern der Seite auf dem Server bringt zwei Vorteile:

  1. Die Seite kann von Bots besser gecrawlt werden (SEO)
  2. Der Benutzer sieht das Resultat der Seitenaufrufe schneller (Core Web Vitals)

Angular SSR und Core Web Vitals

Angular SSR gibt es schon seit sehr vielen Jahren. Es hat aber bisher eine etwas untergeordnete Rolle beim Angular Team gespielt. Dies zeigt sich auch daran, dass die Dokumentation lediglich eine Seite umfasst und dass es in GitHub zahlreiche offene “Issues” gibt. Nichtsdestotrotz hat es eigentlich seinen Zweck erfüllt, bis Core Web Vitals für die Search Engine-Optimierung ein Ranking Faktor wurde.

Im Wesentlichen bestimmt Google mit den Core Web Vitals-Werten die Geschwindigkeit einer Seite. Um hohe Core Web Vitals-Werte zu erreichen, muss der Benutzer die Seite, die er aufruft, sofort vollständig sehen und sie sollte auch sofort interaktiv sein.

Dies ist mit dem Prozess, wie Angular eine Seite aufbaut, nicht ganz einfach zu erreichen.

Wie oben geschrieben, wird die Seite zweimal aufgebaut:

  1. Auf dem Server
  2. Auf dem Browser

Wenn es zu einer Differenz zwischen dem Aufbau der Seite auf dem Server und dem Aufbau im Browser kommt, führt dies zu einem Layout Shift. Core Web Vitals betrachtet einen Layout Shift als nicht vollständig aufgebaute Seite, was zu schlechten Werten führt. Als Entwickler muss man dafür sorgen, dass der Code so implementiert ist, dass es zu keinen Layout-Verschiebungen kommt - der DOM muss in beiden Fällen identisch sein.

Die Wichtigkeit eines CDN und des Cachen der HTML Seite

Damit eine auf dem Server gerenderte Seite rasch dem Benutzer übermittelt werden kann, muss diese natürlich auch auf dem Server schnell aufgebaut werden. Je mehr JavaScript ausgeführt werden muss, desto langsamer ist der Aufbau der Seite. Das Hinzufügen von weiteren Bibliotheken wie z.B. Angular Material, verlangsamt die Ausführungsgeschwindigkeit zusätzlich. Allerdings möchte man auf sinnvolle Bibliotheken auch nicht verzichten.

Diagramm wie eine Angular Seite im CDN und REDIS Cache in der Google Cloud gecacht werden

Neben der Optimierung des Codes mit “Lazy Loading” (es wird nur der Code ausgeführt und übermittelt, der gerade für den Aufbau der Seite gebraucht wird), erreicht man aus meiner Sicht für eine “grosse” Angular Anwendung eine schnelle Übermittlung der Seiten nur durch das Cachen der HTML-Seiten. Mit dem Cachen des HTML muss das JavaScript nicht mehr ausgeführt werden. Die Seite steht bereits gerendert im Cache zur Verfügung. Dies kann mit Hilfe eines CDN (Content Delivery Network) und durch das Cachen in REDIS geschehen. Für Letzteres steht die ausgezeichnete ISR Bibliothek von Enea Jahollari zur Verfügung! Zusätzlich müssen die Assets (JavaScript, CSS, Bilder) im CDN gecacht werden.

Eine weitere Strategie ist das “Prerendern” der Seiten. Dabei werden die Seiten bereits bei der Publizierung der Anwendung erstellt. Diese Strategie ist allerdings nur sinnvoll, wenn der “Content” weitgehend statisch ist. Für eine E-Commerce-Lösung mit sich ändernden Produkten und Preisen ist eine solche Strategie weniger praktikabel.

Optimieren von Bildern

Neben dem Cachen ist die Bildoptimierung ein wichtiger Bestandteil für gute Core Web Vitals-Werte. Bilder müssen in optimalen Grössen und mit optimaler Komprimierung bereitgestellt werden. Angular stellt dazu eine Direktive zur Bildoptimierung zur Verfügung.

Die Wichtigkeit eines kleinen JavaScript Bundles

Das Hauptproblem, um gute Core Web Vitals-Werte zu erreichen, ist die Zeit, die es braucht, bis mit der Anwendung interagiert werden kann. Dafür muss das JavaScript Bundle möglichst schnell geladen und verarbeitet sein. Ein kleines JavaScript Bundle verkürzt die Lade- und Verarbeitungszeit. Mit dem Cachen des JavaScript Bundles im CDN kann die Ladezeit weiter optimiert werden. Ein langsames Netz und schwache mobile Geräte sind der Flaschenhals.

Chrome Entwicklungstools zur Verbesserung der Core Web Vitals-Werte

Wenn man die Anwendung für Core Web Vitals optimiert, ist es wichtig, dass man die monierten Punkte in den Lighthouse Reports der Chrome Entwicklungstools so weit wie möglich behebt. Es ist ebenfalls wichtig zu wissen, dass man die wahren Core Web Vitals-Werte der Google Search Console entnehmen und sehen kann, wie schnell die Seite für die Benutzer wirklich ist. Pagespeed Insights ist nur beschränkt aussagekräftig, da die Werte mit einem stark gedrosselten Netzwerk und einem schwachen mobilen Gerät berechnet werden. Für solche Konstellationen ist Angular SSR zumindest bis jetzt nicht geeignet.

Core Web Vitals und “Soft Navigation”

Nachdem das JavaScript einer Angular Anwendung im Browser ausgeführt wurde (Hydration) ist die gesamte Anwendung geladen und es erfolgen keine vollständigen Seitenaufrufe mehr auf dem Server. Die Navigation zu einem weiteren URL ist danach blitzschnell, was natürlich zu einer sehr gute Benutzererfahrung führt. Man nennt diese Art der Navigation auch “Soft Navigation”.

Leider trägt Core Web Vitals „Soft Navigations“ nur bedingt Rechnung, was aber erkannt wurde und geändert werden soll.

Wie relevant sind die Core Web Vitals-Werte für SEO

Wie geschrieben sind die Core Web Vitals-Werte ein Ranking-Faktor von vielen. Google liebt schnelle Seiten, aber nach wie vor ist guter, hilfreicher Content, der sauber strukturiert und barrierefrei ist, weitaus wichtiger. Noch wichtiger ist, dass die Seite die Autorität zu einem Thema besitzt und gut besucht wird, um eine Platzierung in den Suchresultaten an vorderster Stelle zu erreichen. Umfangreicher Content und Backlinks sind dafür mehr als hilfreich.

Zukunft von Angular SSR mit Zoneless und Event Replay

Core Web Vitals hat die ganze JavaScript Framework-Landschaft umgekrempelt. Das Rendern auf dem Server und die Minimierung des JavaScripts, welches initial an den Browser übermittelt wird, hat drastisch an Bedeutung gewonnen. Diesem Trend hat sich erfreulicherweise auch Angular nicht entzogen. Bei Angular spricht man auch von einer Angular-Renaissance. Die Zusammenführung von Angular mit dem Google internen JavaScript Framework Wiz, welches für Hochgeschwindigkeits-Anwendungen verwendet wird, zeigt ebenfalls, dass ein Wandel stattfindet.

Angular Anwendungen verwenden bisher die Bibliothek Zone.js, um Änderungen von Daten feststellen zu können. Zone.js stellt mit Hilfe von Wrappern der nativen DOM Events und XHR-Aufrufen selbst fest, wenn sich etwas an den Daten geändert hat. Dies ist aber mit JavaScript und mit mehreren Abfragezyklen verbunden. Bei zoneless-Anwendungen werden Änderungen nur ausgeführt, wenn Angular einen Hinweis erhält, dass sich etwas geändert hat. Hier kommen nun “Signals” ins Spiel, die Angular mitteilen, dass Änderungen ausgeführt werden müssen. “Signals” sind Wrapper um Werte, die anzeigen, wenn sich ein Wert geändert hat. Anders gesagt: der Entwickler ist bei zoneless Anwendungen dafür verantwortlich, Angular mitzuteilen, dass eine Änderung stattgefunden hat.

Event Replay ist ein weiteres Konzept, welches zu einer Reduzierung von JavaScript führen wird. Dieses befindet sich im Moment noch in einer experimentellen Phase. Mehr kann dazu dem Angular Blog entnommen werden.

Zoneless-Anwendungen und weitere innovative Konzepte sollten die Ausführungsgeschwindigkeit einer Angular Anwendung deutlich verbessern, was auch zu einem schnelleren Seitenaufbau auf dem Server führt.

Schlussüberlegungen

Durch aggressives Cachen sind die Core Web Vitals-Werte der URLs des aXpel Shops in der Google Search Console sowohl für Mobile als auch für Desktop alle im grünen Bereich.

Der Aufwand für die ganzen Optimierungen und das Cachen ist hoch. Bei Angular SSR muss man auch bedenken, dass der Benutzer für eine Session immer nur einen URL vom Server aufruft. Bei allen weiteren Seitenwechseln handelt es sich um “Soft Navigations”. Dies bedeutet, dass man mit einem Service dafür sorgen muss, dass alle relevanten URLs in den REDIS Cache bzw. in das CDN gelangen, da man nicht weiss, über welchen URL der Benutzer in die Angular App einsteigt (z.B.Produkt, welches gegoogelt wird).

Idealerweise sollte eine Seite bereits ohne das Cachen des HTML genügend schnell sein. Das CDN ist dann ein zusätzlicher Bonus.

Trotz aller zukünftigen Verbesserungen in Angular, denen ich positiv entgegensehe, und dem sehr guten Benutzererlebnis einer Angular Anwendung bin ich mir nicht sicher, ob ein Multipage Framework für SEO-relevante Anwendungen nicht doch die bessere Wahl ist. Mit einem solchen kann das JavaScript Bundle minimal gehalten werden und ohne Hacks schnelle Seiten erstellt werden. Dadurch, dass mit jeder Navigation die vollständige Seite vom Server (bzw. CDN) geladen wird, kann diese automatisch in das CDN gelangen. Interessant ist auch eine Entwicklung in Chrome, welche das spekulative Cachen von URLs erlaubt. Dabei werden ausgehend von der ersten geladenen Seite weitere Seiten im Hintergrund nachgeladen und im Browser Cache gespeichert. Wie bei einer SPA sind dann weitere URL Aufrufe blitzschnell.

Das in allen Bereichen ausgezeichnete Entwickler-Erlebnis in Angular möchte ich allerdings auch in Zukunft nicht missen.