15.02.2023

Lesezeit: 2 Minuten

Weiterentwicklung von Websiteprojekten bei der dkd

Aufmerksame Leser des dkd Blogs wissen, worauf bei Updates und Upgrades alles geachtet werden muss und wie viel Arbeit in diesen Prozessen steckt. Im Blogartikel von April 2021 erwähnt mein Kollege Alexander Degelmann auch kurz, dass automatische Tools zu den guten Praktiken zählen. Hier wollen wir jetzt einmal etwas tiefer in genau diese nicht-menschlichen Hilfsmittel einsteigen und uns ansehen, was aus der Perspektive unseres Continuous Integration Servers genau passiert.

1. Die Entwicklung tut ihren Job

Entwickler:innen tun, was Entwickler:innen tun und tippen Anweisungen an den Computer in ihre Entwicklungsumgebungen ein. Die Code-Änderungen werden auf den git-Server verfrachtet und mit einem Quäntchen Glück hat das Entwicklungstierchen vor der Tastatur vorher darüber nachgedacht, was es da eigentlich tut. Falls nicht, gibt es immer noch den menschlichen Review- und Testprozess, der viele Fehler finden, und vor der Veröffentlichung ausmerzen kann. Gerade im Home Office aber gehen diese Tests oft mit ritualistisch anmutenden Tänzen einher, deren charakteristisches Merkmal ein Ausreißen der eigenen Haare ist. Hier helfen bereits erste Tools auf der Ebene des Continuous Integration Systems.

Noch bevor ein zweites Paar menschlicher Augen überhaupt einen Blick auf den Code werfen kann, ist der Continuous Integration Server schon beschäftigt und prüft einfach zu automatisierende Dinge: Stimmt die Formatierung mit den Vorgaben überein? Sitzen alle Klammern an der richtigen Stelle und sind die Kommata korrekt gesetzt? Gibt es Konflikte, die im Weg stehen, den Code in seiner aktuellen Form zu übernehmen?
Wir leisten damit unseren Beitrag zum Schutz des - soweit noch vorhandenen - Haupthaars unserer Dev-Teams. Nebenbei machen wir den Code lesbarer und senken damit die Kosten für Wartung und Erweiterung, aber das Hauptaugenmerk liegt definitiv auf der Haarpracht der Kolleg:innen!

Und sonst so?

Damit ist alles gesagt, oder? Server prüfen den Code auf gute Formatierung, Entwickler:innen prüfen den Code auf Dinge die besser gelöst werden könnten, Fehler, veraltete Versionen, Sicherheitslücken in verlinkten Paketen, Performanz... Moment mal! Wenn das alles durch einen Menschen geprüft werden müsste, dann würde so ein Review doch mehrere Tage dauern!
→ Bitte alle, die keine weitere Automatisierung erwartet haben, jetzt schockiert einatmen.

Eine Sekunde ist kurz...

... aber wenn wir nur 60 zusammenlegen, dann ergibt es eine ganze Minute.

OK, machen wir erstmal einen Schritt zurück und erklären kurz, wie eine Website geladen wird. Der Browser erhält die Anweisung unsere Seite zu zeigen und fragt bei seinem eingestellten DNS-Server nach, wo denn diese Adresse zu finden sei. Sobald die Antwort vorliegt verbindet sich der Browser mit dem Webserver, fragt die konkrete Adresse an und der Server antwortet mit dem Quelltext der gewünschten Seite.
Der Browser interpretiert diesen Quelltext (HTML) und prüft, welche Ressourcen noch zusätzlich geladen werden müssen (z.B. CSS, Bilder, Javascript), weil sie im Code referenziert sind.
Bei CSS-Dateien und Bildern ist das in der Regel unproblematisch, da diese meist auf dem gleichen Server liegen und mit modernen Techniken wie HTTP2 bereits vom Server an den Browser gesendet werden können, bevor der Browser überhaupt realisiert hat, dass er diese Ressourcen benötigt. Selbst ohne so eine Beschleunigung ist das Laden dieser Ressourcen aber zeitlich nicht wirklich problematisch, auch weil die Verbindung zum Server bereits besteht.

Bei Javascript sieht das aber etwas anders aus: Werden Bibliotheken wie jQuery, React oder Angular verwendet, dann werden diese häufig über eine externe Referenz eingebunden, für die der Browser möglicherweise erst wieder über DNS die Adresse auflösen muss, bevor überhaupt die Verbindung zum Server hergestellt werden kann, um die Anfrage zum Download zu senden. Aber dann bleibt es ja nicht bei einem Frontend Framework; externes Cookiebanner, Analytics, Tracking… Und diese können ihrerseits wieder Abhängigkeiten haben, die geladen werden müssen.

Webpack ist ein Tool, das diese Abhängigkeiten zu Modulen zusammenfasst und gemeinsam ausliefert. Anstelle auf ein Dutzend Serververbindungen und Paketdownloads zu warten, liefert Webpack wenige, zusammengefasste Dateien aus.
Darüber hinaus tut Webpack auch noch hilfreiche Dinge für die Devs: Stellen wir uns vor, zwei eingebundene Javascript-Bibliotheken würden das gleiche, externe Paket benutzen, aber in unterschiedlichen Versionen. Ob dann die Seite richtig ausgegeben wird, wird damit zum Glücksspiel.
Auch hier hilft Webpack mit der Zusammenfassung in Modulen und der damit einhergehenden Trennung der Pakete untereinander. Der Effekt: Volles Haar ohne unnötige kahle Stellen bei den technisch Verantwortlichen und wir minimieren die Anzahl von Webseiten, die Ihre Besucher:innen aufrufen müssen, um eine ganze Minute Wartezeit einzusparen.

Versionskontrolle

Und damit ist nicht git gemeint, sondern ein Tool namens Renovate. Renovate macht Dinge, die so ein Entwicklungs- oder Supportteam eigentlich gar nicht kosteneffizient leisten kann: Es prüft in regelmäßigen Abständen, ob es neue Versionen der eingebundenen Pakete gibt. Wenn neue Versionen gefunden werden, aktualisiert Renovate selbstständig die Abhängigkeiten und legt einen Merge Request an. Hier werden vorher definierte Benutzerkonten als zuständig für diese Aktualisierungen angegeben, so dass immer die richtige Benutzergruppe über Aktualisierungen informiert wird.
"Aber das dauert höchstens fünf Minuten, wir machen das von Hand!" - Klar, diese Updates muss man nicht automatisieren. Aber jede von Hand eingetippte Zahl erhöht das Potential für menschliche Fehler, und auch wenn diese Prüfung nur 5 Minuten je Woche dauert, kommen auf diese Weise fast viereinhalb Stunden im Jahr zusammen. Und das pro Projekt! Renovate gibt den Devs damit die Möglichkeit, sich auf die wirklich wichtigen Dinge zu fokussieren.

Jetzt einfach kopieren

Der git-Server hat den Code analysiert und keine Probleme festgestellt. Der menschliche Review ist erfolgt, im Releasepaket hat Webpack die Javascript-Dateien zusammengefasst und Renovate hat geprüft, ob Pakete aktualisiert werden müssen. Der aktuelle Entwicklungsstand kann also zum Integrationstest geladen werden.
Jetzt ist so ein Rollout von einem Webprojekt scheinbar total einfach: Alle Dateien, die sich geändert haben, auf den Server hochladen und fertig. Oder?

Nicht ganz. Wir müssen sicherstellen, dass während des Hochladens der Dateien niemand versucht, auf die Seite zuzugreifen, um Fehler auf der Webserverebene zu verhindern. Neuen Dateien müssen auf dem Server die richtigen Rechte zugewiesen werden. Es muss sichergestellt sein, dass gerade in diesem Moment nicht irgendein Prozess läuft, der auf Projektdateien zugreift, Caches müssen geleert werden, Datenbankmigrationen müssen durchgeführt werden, wenn sich etwas an der Datenstruktur geändert hat… Das sind ja wieder so viele Dinge auf einmal, die sich kein Mensch merken kann, und die damit wieder total fehleranfällig sind!

OK, hier im sechsten Absatz dieses Blogartikels gewinne ich keinen Blumentopf mehr, wenn ich hier von automatisierten Deploymentsystemen spreche, die genau diese ganzen Aufgaben übernehmen. Genauer macht das aktuell dkdeploy, unser selbst entworfenes Werkzeug, um Webapplikationen mit einem einzigen Befehl (bzw. einem Mausklick auf dem CI Server) zu aktualisieren. In der Regel sind in dkdeploy je Projekt mehrere Umgebungen definiert, so dass eine Veröffentlichung auf der lokalen Entwicklungsumgebung, der Integrationsumgebung, einer Testinstanz und schließlich dem Produktivsystem möglich ist.

Performanz

Die beste Website, mit den aktuellsten und relevantesten Informationen, verfehlt ihren Zweck, wenn jede Seite Minuten braucht, bis überhaupt Inhalte gezeigt werden - bis dahin haben sich weite Teile der Besucherschaft eine alternative Informationsquelle gesucht und diese schlimmstenfalls bei Wettbewerber:innen gefunden.

Sitespeed.io anaylsiert die verschiedenen Performance-Metriken eines Websiteprojekts (Ladezeiten für Bilder, Ausführungszeit von Client-Side-Code, HTML-Seitenrendering, um nur einige zu nennen) und warnt, wenn vorab definierte Grenzwerte überschritten werden. Das Schöne daran: Der Test wird auf einem echten Webserver ausgeführt. Wie super die Seite auf der lokalen Entwicklungsumgebung läuft ist daher egal! Schade, eigentlich - das ist eine der Lieblingsausreden von Menschen, die in der Softwareentwicklung arbeiten.

Fazit

Lasst Devs machen, was Devs gut können. Für den Rest gibt es Maschinen, die wiederholbare Prozesse genauer und schneller ausführen als es ein Mensch könnte.
Ich versuche mal ein Research-Projekt bei der Geschäftsführung durchzukriegen: Neuronale Netze zum Schreiben von Blogartikeln - das kann man doch bestimmt automatisieren ;-).