Schlank & schnell: wie wir den Spielplan der Staatsoper Berlin performanter gemacht haben

Artikel von: Søren
Veröffentlicht am: 2024-05-31

In diesem Beitrag

Schnelle Ladezeiten und vor allem schnelle Interaktivität (was wir unter „Performance“ zusammenfassen) sind mit entscheidend dafür, dass sich eine Website oder Webanwendung bei der Nutzung „gut anfühlt“. Eine besondere Herausforderung sind dabei filterbare Listen von vielen Einträgen, wie sie etwa im Online-Shop des Vertrauens vorkommen. Auch unser langjähriger Kunde, die Staatsoper Unter den Linden in Berlin, hat einen wichtigen Anwendungsfall für die Darstellung einer großen Menge von Datensätzen: den Spielplan.

Das Problem: 450 Termine, 1 Browser

Gerade zu Bekanntgabe des Programms für die nächste Spielzeit ist der Spielplan prall gefüllt mit allen zukünftigen Terminen der kommenden Monate. Im Mai 2024 standen wir genau vor dieser Situation mit 450 Terminen von Opern, Konzerten, Ballettaufführungen und weiteren Veranstaltungen. Zu diesem Zeitpunkt wurde der Spielplan noch auf dem Server berechnet und als ein großes HTML-Dokument mit der kompletten Liste von Terminen an den Browser geschickt. Dieses Vorgehen ermöglichte zwar eine Filterung nach Sparte oder Zeitraum mit JavaScript, bedeutete aber auch, dass der Browser eine große Menge von Daten laden und verarbeiten musste. Insbesondere der für die Filterung nötige JavaScript-Code schlug hier stark ins Gewicht.

Für mobile Endgeräte, deren Leistung eher in der Mittelklasse angesiedelt ist, kann eine Website mit vielen Elementen oder einer großen Menge an JavaScript-Code eine Verzögerung von Anzeige und Nutzbarkeit im Sekundenbereich bedeuten. Da die Wechselwirkung von Website-Performance und -Erfolg ("Konversionsrate") gut belegt ist, hatten wir gemeinsam mit der Staatsoper Berlin ein strategisches Ziel ausgerufen: Wir wollten die Zeit bis zur Anzeige und Interaktivität des Spielplans deutlich verringern. Um den Erfolg zu überprüfen, würden wir gängige Messwerte wie Googles Core Web Vitals und Serien von Screenshots nutzen, die alle 0,1 Sekunden während des Ladevorgangs aufgenommen werden.

Unsere Lösung: Paginierung und Infinite Scrolling

Das Projekt war klar umrissen: Wir wollten die Größe des HTML-Dokuments verkleinern und die Menge an rechenintensivem JavaScript-Code möglichst gering halten. Frei nach „Divide et impera“ ist die Lösung für die erste Teilaufgabe, die lange Liste aller Termine nicht auf einer einzigen Seite zu rendern, sondern auf viele Seiten verteilt. Mit einer paginierten Darstellung von 10 Terminen pro Seite würden wir bei durchschnittlich 1-3 Vorstellungen am Tag etwa 5-6 Tage abdecken.

Die Aufteilung bedeutet aber, dass eine Nutzerinteraktion nötig ist, um auf die nächste Seite zu navigieren. Zusätzliche Klicks würden das Durchstöbern des Spielplans stören und sich negativ auf die Nutzerbindung auswirken. Wir haben daher mit „Infinite Scrolling“ ein Muster implementiert, das von sozialen Netzwerken und anderen großen Plattformen bekannt ist. Statt per Klick auf die nächste Seite navigieren zu müssen, werden die nächsten Termine im Hintergrund schrittweise nachgeladen, wenn Nutzerinnen und Nutzer nach unten scrollen. Damit ändert sich an der Art der Bedienung nichts, die Ladezeit des ersten Pakets von nur noch 10 Terminen verkürzt sich aber dramatisch.

Das konnten wir uns bei der zweiten Teilaufgabe zu Nutze machen. Um möglichst viel JavaScript-Code entfernen zu können, stellten wir die Filterung des Spielplans auf eine serverseitige Lösung um. Wo eine Eingrenzung auf eine Sparte oder einen Zeitraum zuvor zu Verzögerungen führte, während das JavaScript die Filterung vornahm, würden wir zukünftig eine neue Anfrage an den Server ausführen, der ein neues HTML-Dokument zurückliefert. Das braucht deutlich weniger JavaScript-Code und wir konnten die Dateigröße von 136 kB auf 9 kB reduzieren. Die Dateigröße steht hier nur stellvertretend für die letztendlich eingesparte Rechenzeit, denn weniger Code ist auf allen Geräten schneller ausgeführt.

Das Ergebnis: Eine halbe Sekunde kürzere Ladezeiten

Bereits kurz nachdem wir den Spielplan Mitte Mai 2024 auf die neue Implementierung umgestellt hatten, wurden bei Googles Core Web Vitals im Chrome UX Report (echte Nutzerdaten, letzte 28 Tage) Verbesserungen sichtbar – und das, obwohl die Umstellung nur für die Hälfte des Messzeitraums aktiv war. Auch synthetische Tests zeichneten ein erfolgreiches Bild: In Messungen mit dem Tool WebPageTest zeigte sich für ein simuliertes iPhone X über eine 4G-Verbindung eine Verbesserung der Ladezeit von 2,2 s auf 1,7 s – eine halbe Sekunde schneller!

Durch die Optimierungen ist der neue Spielplan eine halbe Sekunde schneller fertig geladen.

Schön ist auch zu sehen, dass die Belastung des Browsers (und des Prozessors des Endgeräts) stark zurückgegangen ist: Durch die Reduktion von HTML-Elementen und JavaScript-Code gibt es keine Blockaden des Main Threads (erster Screenshot, zweite Zeile von unten, sehr hohe Auslastung) durch Long Tasks (erster Screenshot, unterste Zeile, drei rote Blöcke) mehr:

Die nahezu 100%-ige Auslastung in der Zeile "Browser Main Thread" verdeutlicht, wie rechenintensiv die bisherige Lösung war.
Nach der Umstellung zeigt das Diagramm keine nennenswerte Auslastung oder Blockaden mehr.

Auch in Googles PageSpeed Insights ist die Verbesserung signifikant: im Bereich Performance für mobile Geräte erreicht die Spielplan-Seite 88 von 100 möglichen Punkten, was im Vergleich zu vorher (47 von 100 Punkten) beinahe eine Verdopplung ist. Für die Kategorie „Desktop“ erreicht der neue Spielplan sogar 99 Punkte. Das freut uns sehr, zeigt aber auch, dass es vor allem bei mobilen Geräten noch weiteres Verbesserungspotenzial gibt. Performanceoptimierung ist ein Prozess, der immer weiter geht – und wir nehmen die Herausforderung gerne an.

Update 14.06.2024: optimierte Ladereihenfolge kritischer Ressourcen

Diese Woche haben wir den Prozess weiter voran getrieben und die Ladereihenfolge der für gute Performance kritischen Ressourcen optimiert. Hier geht es um Fragen wie:

  • Was soll zuerst geladen werden? JavaScript, CSS oder doch lieber die Web Fonts?
  • Welche einzelnen Ressourcen sind vielleicht nicht kritisch und können ans Ende der Warteschlange gesetzt werden?
  • Wie sollen die Ressourcen geladen werden? Müssen andere Prozesse warten, bis eine bestimmte Ressource verfügbar ist, oder sind die Ressourcen unabhängig voneinander und können asynchron angefordert werden?
  • Wie gehen wir mit den Schriftarten um – zeigen wir eine weiße Seite, bis die Web Fonts geladen sind, oder erst eine generische Ersatzschrift vom Gerät der Website-Besucher*innen?

Mit Hilfe von Harry Roberts' Empfehlungen zur Ladereihenfolge, die er seit Jahren kontinuierlich weiterentwickelt, haben wir unsere Antworten gefunden und umgesetzt. Und die Seite wieder ein bisschen schneller gemacht: Google Pagespeed belohnt uns für die Seite des Spielplans mit nunmehr 93 von 100 Punkten (mobile Geräte).

Interesse geweckt?

Wir hören gerne zu, wenn Sie Fragen oder Anmerkungen zu diesem Thema haben. Und wenn Sie ein Projekt, ein Produkt, ein Problem oder eine Idee mit uns besprechen möchten, freuen wir uns erst recht über ein Gespräch!

Kontakt aufnehmen