06. Mai 2022

Nachhaltige Webentwicklung im Backend

Wer heutzutage eine Webpräsenz betreibt, tut dies meist mit Hilfe eines Content Management Systems. Dieses CMS liefert das Backend und oftmals auch das Frontend einer professionellen Website. Dabei bieten CMS im Vergleich zu statischen Websites den charmanten Vorteil, dass der Betreibende einfach und komfortabel Inhalte bearbeiten und neu erstellen kann. Dies gibt Redakteur*innen einfache Mittel in die Hand, um Inhalte zu erzeugen, führt jedoch natürlich auch zu einer erhöhten Last auf den Servern: Inhalte werden nicht einfach nur in Form von statischem HTML ausgegeben, sondern vorher aus einer Datenbank geladen, dann weiterverarbeitet und schließlich als HTML an den Browser des Betrachtenden ausgeliefert. Das sorgt natürlich für eine gesteigerte Last auf dem Server, da diese Vorgänge ungleich komplexer sind, als das Ausliefern statischen HTMLs.

Warum beschäftigen wir uns mit dem Thema des nachhaltigen Web Developments? Wir wollen das Web nachhaltiger und grüner gestalten, da wir als Unternehmen im IT-Sektor eine gewisse Verantwortung gegenüber dem Klimawandel haben. Dieser wollen wir gerecht werden, in dem wir uns Gedanken über Nachhaltigkeit in der Webentwicklung machen.

Unser Statement zu diesem Thema

Green IT im Backend: Welche Maßnahmen gibt es?

Wenn wir uns Gedanken darüber machen, wie wir eine Website grüner betreiben können, sollten wir uns unbedingt auch mit dem Backend der Website befassen. Dies umfasst die serverseitigen Komponenten wie zum Beispiel die Kommunikation mit der Datenbank und das Rendering des auszuliefernden HTMLs. Ganz allgemein gilt hier die Faustregel: “Je performanter eine Website ist, umso grüner ist sie auch”. Denn natürlich beansprucht eine schnelle Website den Server von dem sie bereitgestellt wird, auch proportional weniger. Wir können also durch Optimierungen den Webserver entlasten und dadurch Strom sparen.

Die Reduzierung des Ressourcenverbrauchs kann im Backend auf unterschiedliche Weise erreicht werden. Im Folgenden geben wir einen Überblick über diverse Techniken und Hilfsmittel. Ein besonderes Augenmerk legen wir hierbei auf das CMS Drupal, mit dem viele unserer Webprojekte durchgeführt werden.

Caching

Ein mächtiges Werkzeug in der Performance-Steigerung ist das Caching. Dabei werden Inhalte zwischengespeichert und bei Bedarf ausgeliefert. Caches gibt es an diversen Stellen. Geläufig ist vielen Nutzer*innen der Browser-Cache. Dieser speichert auf der Client-Seite zum Beispiel Bilder um bei einem erneuten Seitenaufruf die Bilder lokal ausliefern zu können, anstatt sie herunterladen zu müssen. Daneben gibt es auch serverseitige Caches. Wenn Inhalte nur selten oder vorhersehbar oft geändert werden, hilft ein serverseitiger Cache dabei, Seiten, oder auch nur Bestandteile von Seiten, zu speichern. Anstatt sämtliche Daten aus der Datenbank abfragen zu müssen, wird der Cache befragt und liefert die fertig aufbereiteten und gerenderten Inhalte aus. Hier unterscheiden sich natürlich die konkreten Implementierungen je nach verwendetem System.

Drupal hat Caching-Mechanismen direkt im Kern integriert. Der Cache hat eine maximale Lebensdauer, die besagt, wie lang ein Cache-Eintrag haltbar und damit gültig und anwendbar bleibt. Kann man davon ausgehen, dass sich Inhalte nur selten ändern, kann eine hohe Cache-Lebensdauer dafür sorgen, dass die Last auf Server und Datenbank enorm gesenkt wird. Gerade für anonyme Nutzer*innen, die sich nicht auf der Seite angemeldet haben, kann hierdurch die Performance enorm gesteigert werden. Denn meist sehen Gast-Nutzer*innen einer Website alle den gleichen Inhalt, ohne personalisierte Komponenten. Die Website kann also in diesem Fall einmal gecached und immer wieder ausgeliefert werden.

Drupal’s Cache bietet durch die Nutzung von Cache-Tags und Cache-Contexts die Möglichkeit feingranular festzulegen anhand welcher Kriterien ein Cache aufgebaut werden soll. Sie bestimmen von welchen Daten dieser Cache abhängig ist. Ist also beispielsweise ein bestimmter Cache-Eintrag abhängig von verschiedenen Inhalten, so wird er neu aufgebaut, sobald sich einer der abhängigen Inhalte verändert. So können sogar dynamische Inhalte vom Caching profitieren, ohne, dass sie in einem ungültigen Zustand ausgeliefert werden.

In dieser beispielhaften Implementierung sehen wir, wie in Drupal das Caching eines Inhalts in Abhängigkeit zu einem Konfigurationswert gesetzt werden kann. Sobald dieser Wert sich ändert, wird der Cache des Blocks invalidiert und bei erneuter Anfrage neu gerendert und im Cache abgelegt.

Außerdem kann Drupal dynamische Listen, die mit Hilfe des Views-Moduls erzeugt werden, vorhalten und für eine bestimmte Dauer cachen. Das ist sehr hilfreich, da gerade Views eine hohe Last auf der Datenbank erzeugen, wenn die nötigen Inhalte aggregiert werden.

Drupal’s Cache ist sogar in der Lage mit Platzhaltern zu arbeiten. Wenn auf einer Seite nur ein kleiner Teilbereich hoch dynamisch ist und sich oft ändert, sind Platzhalter ein sinnvolles Werkzeug. Sie ermöglichen es den Entwickler*innen trotz des dynamischen Teils der Seite Caching zu nutzen. Der kleine dynamische Teil wird dann im Cache ausgelassen und mit Hilfe eines Platzhalters nach dem Laden aus dem Cache wieder eingefügt.

Wer sich weiter in Caching einarbeiten möchte, dem lege ich die Session meines Kollegen Kristiaan van den Eynde auf der DrupalCon 2019 in Amsterdam ans Herz, in der er einen Einstieg in die Verwendung von den in Drupal 8 vorhandenen Cache Systemen liefert:

Responsive Images & Image Optimizations

Heutzutage wird eine Website nur noch selten auf einem Desktop Computer betrachtet. Die Landschaft der verschiedenen internetfähigen Endgeräte wird immer diverser und damit ihre Berücksichtigung in der Webentwicklung immer relevanter. Mobile first ist mittlerweile der Industriestandard. Doch auch darüber hinaus können Websites für mobile Endgeräte optimiert und damit beschleunigt werden.

Beispielsweise können Bilder in einer für den kleineren Bildschirm eines Smartphones oder Tablets passenden Auflösung ausgeliefert werden. Indem wir statt nur einer Bildquelle eine ganze Liste an Bildquellen mit den zugehörigen Media-Queries angeben, kann sich der Client selbst die passende Bildvariante aussuchen. Das spart Bandbreite, da keine Bilder geladen werden müssen, die ohnehin zu groß sind, um sie in voller Größe anzuzeigen.

Image showing a plant growing our of a flower pot. The flower pot symbolizes the image that is being displayed on various devices, that are shown as leaves of the plant.

HTML liefert mit dem srcset Attribut des Image-Tags und den Source-Tags innerhalb eines Picture-Tags bereits den Grundstein hierfür: Wir sind in der Lage verschiedene Bildquellen für unterschiedliche Auflösungen anzugeben und so dafür zu sorgen, dass Nutzer*innen nicht unnötig großes Bildmaterial für kleine Bildschirme herunterladen müssen, dennoch aber HiRes Versionen für große Viewports zur Verfügung stehen.

Das sieht in der Praxis ungefähr so aus:

Der Client wählt aus den gegebenen Derivaten die Version aus, die zur verwendeten Auflösung passt.

Außerdem lohnt der Einsatz moderner Bildformate wie .webp. Die Kompression ist gut und die resultierenden Dateien kleiner als ihre Äquivalente in .png oder .jpeg. Auch wenn noch nicht alle Browser (Looking at you, IE) .webp unterstützen hilft uns hier wieder die Verwendung des oben beschriebenen srcset-Attributs von HTML aus. Gibt man als eine der Bildquellen .webp-Dateien an, wählt der Browser dieses, wenn es ihm möglich ist. Ist es das nicht, wird auf alternative Versionen zurückgegriffen. Durch mehrere Source-Elemente mit dem gleichen Media-Query können wir hier Alternativen anbieten.

Drupal hat bereits die Module image styles und responsive image im Kern. Durch die Verwendung der Module können Redakteur*innen Bilder im System hochladen. Diese werden automatisch auf konfigurierte Bildgrößen zugeschnitten und mit Hilfe von responsive images gerendert um die bestmögliche Bildvariante für den verwendeten Viewport zu liefern. Nimmt man noch das Modul webp aus der Drupal Community dazu, hat man eine Lösung, die out of the box responsive Images zusätzlich als webp ausspielt.

Und wenn wir schon dabei sind Bilder zu optimieren, lohnt es auch über Lazy Loading nachzudenken. Bei dieser schon nicht mehr ganz jungen Technik werden Bilder erst dann geladen, wenn sie tatsächlich für den aktuellen Viewport sichtbar werden. Das spart Requests und steigert die Performance, wenn viele Bilder auf einer Seite dargestellt werden. Für Drupal gibt es hierzu das Modul Blazy das genau diese Technik mitbringt.

CDN

Durch die Verwendung eines Content Delivery Networks (CDN) kann eine Website weiter beschleunigt werden. Hierbei wird zur Auslieferung von Ressourcen auf einen Drittanbieter gesetzt, der hierauf spezialisierte Server zur Verfügung stellt. Kommt ein CDN zum Einsatz wird die Latenzzeit beim Zugriff auf Ressourcen verringert: Ein unabhängiges, über geographisch sinnvolle Standorte verteiltes Netzwerk von Caching Servern sorgt dafür, dass Inhalte für die Auslieferung nur möglichst kurze Routen zurücklegen müssen. Das senkt den Energieverbrauch der Netzinfrastruktur und beschleunigt die Auslieferung der Ressourcen. Drupal bietet durch die Verwendung von Modulen Anbindungen an diverse CDNs womit diese für Ressourcen innerhalb ihrer Drupal-Installation verwendet werden können.

JS und CSS aggregieren und minimieren

Durch die Auslieferung von minifiziertem Javascript und CSS kann Bandbreite gespart werden. Drupal ist modular aufgebaut, was zur Folge hat, dass jedes einzelne Modul CSS und JS mitliefert. Das führt dazu, dass häufig mehrere Dutzend Dateien übertragen werden müssen um eine Website darstellen zu können. Drupal bietet durch die Aggregation von CSS- und JS-Dateien eine nützliche Optimierung. Denn statt vieler kleiner Dateien muss nur eine große ausgeliefert werden, wodurch die Anzahl der Anfragen an den Server massiv reduziert werden kann.

Reduktion im Produktivsystem

Drupal 8 hat die Möglichkeit, für verschiedene Umgebungen einer Website verschiedene Konfigurationen zu nutzen. Beispielsweise kann einer Staging- oder Testumgebung eine andere Konfiguration zugrunde liegen, als dies für die Produktivumgebung der Fall ist. Die Konfiguration enthält praktisch alle veränderlichen Daten, die für Drupal notwendig sind, um funktionieren zu können.

Wir können die Performance von Drupal (wenn auch in neueren Versionen nur ein wenig) steigern, indem wir Module im Produktivsystem abschalten, die dort ohnehin keinen Nutzen erfüllen. Beispielsweise stellt Drupal durch Views ein mächtiges Werkzeug zur Verfügung, um dynamische Listen von Inhalten zu konfigurieren und diese in Form von Seiten oder Inhaltsblöcken in der Website anzuzeigen. Zusätzlich gibt es das Modul ViewsUI, die Nutzeroberfläche für Views. Damit können Views erstellt werden, was im Entwicklungsprozess praktisch ist. Zur Darstellung einer View ist das Modul aber nicht notwendig. Auf professionellen Seiten mit angeschlossenen Deployment Prozessen hat es ohnehin keinen Nutzen, weil Änderungen nur in lokalen Entwicklungsumgebungen erfolgen. Man kann also bestimmte Module in der Produktivumgebung deaktivieren, die dort nicht gebraucht werden. Denn alleine dadurch, dass ein Modul aktiviert ist, verschlechtert sich die Performance der Seite. Bei jedem einzelnen Modul sollte aber klar abgewogen werden, ob es tatsächlich nutzlos im Produktivsystem ist.

Optimaler Quellcode

Bei allen Eigenentwicklungen sollten wir darauf achten, dass wir unseren Code optimieren. Für viele Entwickler*innen mag das banal klingen, aber es ist deshalb nicht weniger wichtig! Wenn wir unseren Quellcode optimieren und beispielsweise unnötige Funktionsaufrufe einsparen und Zwischenergebnisse speichern statt Berechnungen immer wieder auf’s neue durchzuführen, sparen wir bei Berechnungen und Operationen wertvolle Rechenzeit. Die hierdurch erzielbare Energieeinsparung bei einer stark frequentierten Website oder einem viel genutzten Web-Service summiert sich schnell zu einer beeindruckenden Menge auf.

Beispiel gefällig? Hier einer meiner Lieblings-Anfängerfehler aus der Drupal-Welt:

Dieser Code soll Dinge mit Inhalten tun, die bestimmte Kriterien erfüllen. Die beispielhaften Kriterien sind hier der Inhaltstyp (= basic_page) und der Wert im Feld field_my_field (= foo). Der Code wird funktionieren und tun, was er soll. Jedoch laden wir mehr Inhalte, als nötig, um zu prüfen, ob die Kriterien erfüllt sind.

Das können wir vermeiden, indem wir einen maßgeschneiderten Entity-Query verwenden:

Statt Nodes zu laden, und sie dann zu untersuchen, laden wir nur diejenigen, die tatsächlich den Kriterien entsprechen. Auch wenn wir komplexere Kriterien prüfen müssen und beispielsweise Felder einer referenzierten Subentität betrachten, müssen wir dazu nicht die Node für einen Zugriff auf die Felder der referenzierten Entität laden. Stattdessen kann auch diese Bedingung über den Entity-Query formuliert werden:

Das Formulieren eines, wenn auch komplexen Entity Queries ist dabei sehr viel performanter, als das manuelle Laden und überprüfen der Entitäten. In manchen Fällen ergibt möglicherweise auch der Einsatz eines Static Queries oder eines Dynamic Queries Sinn um die Performance weiter zu verbessern. Wer ganz genau wissen möchte wo sich im Code ungeahnte, Performance fressende Engpässe verbergen, dem lege ich außerdem den Profiler von XDebug ans Herz, der dabei hilft, genau diese zu identifizieren und zu beheben.

Fazit

Es gibt diverse Ansätze um ein Backend grüner zu machen. Die hier aufgelisteten Ansätze sind nur ein Bruchteil der Möglichkeiten. Möglicherweise stellt sich jetzt die Frage: “Und wie soll ich das meinen Auftraggeber*innen verkaufen?” Ganz einfach: Jede Optimierung die auf das Konto der grünen Webentwicklung einzahlt, bietet im Umkehrschluss auch einen weiteren Mehrwert: Gesteigerte Performance und damit eine höhere Geschwindigkeit der Website. Und wir Webentwickler*innen wissen wie wichtig es ist, Performance-Optimierungen ernst zu nehmen. Google mag performante Seiten; wir steigern das SEO Ranking. Nutzer*innen mögen performante Seiten; wir senken die Absprungrate und steigern potenziell die Konversionsrate. 

Nachhaltigkeit in der Webentwicklung ist also nicht gleichzusetzen mit Mehrkosten. Ganz im Gegenteil kann eine auf Nachhaltigkeit optimierte Website ihren Erfolg und auch den mit ihr erzielten Umsatz steigern. Wenn es also innerhalb eines Webprojekts nicht gewollt ist, einen Beitrag zur Rettung unseres Planeten zu leisten, dann ist es aber sicher gewollt das Endprodukt so erfolgsversprechend wie möglich umzusetzen. Das Konto auf das wir einzahlen, ist das gleiche. Nur die Blickwinkel unterscheiden sich.

Mathias Wächter

Mathias Wächter

Backend Developer

mathias@factorial.io