Stranger Than Usual

Webbloat reduzieren

In den letzten Wochen habe ich beruflich an einer Angular-App gearbeitet. Der Kunde nutzt überall Angular, und möchte das auch hier nutzen. Der Kunde hat auch schon eine Bibliothek mit ordentlichen Komponenten, passend zum Corporate Design. Das Projekt ist für mich insofern ungewöhnlich, dass ich sonst nie reine Frontendarbeit mache, sondern sonst immer Backend und Frontend. Aber das ist hier irrelevant.

Wir haben die Entwicklung also vor knapp vier Wochen gestartet. Vorher war die App leer. Die App macht bisher auch nicht viel, der Kunde will erst einmal einen Klickdummy für eine Schulung, und die Backend-Endpunkte (wie gesagt, ein anderes Team) sind sowieso noch nicht fertig. Bzw. es wurde noch nicht damit angefangen (ja, ich weiß, das wird höchstwahrscheinlich noch… interessant).

Diese Woche habe ich mal darauf geschaut, wie groß das Javascript unserer App ist. Fuck! 1,5 MiB. Dabei macht die App praktisch noch nichts. Keine komplizierten, ungewöhnlichen Protokolle in den Abhängigkeiten, wie z.B. bei der Winkekatzenseite der Fall ist. Nur Standard-Angular und die Komponentenbibliothek, die der Kunde bereitstellt (von der nur ein Bruchteil tatsächlich genutzt wird).

So schnell geht es also, das Javascript (und CSS) unnötig aufzublähen. Seit ich auf so etwas achte (auch bei Websites, an denen ich nicht selber arbeite, ich bin das schon fast so obsessiv wie mit Datenkompression) habe ich mich immer gefragt, wieso so viele Seiten so groß sind, obwohl ihr Content das bei weitem nicht rechtfertigt. Meine aktuelle Hypothese: Es ist zu einfach. Man nimmt ein bisschen Bequemlichkeit (ein JS-Framework hier, eine Komponentenbibliothek da) und – schwupps! Alles ist riesig, und der größte Teil davon wird nicht gebraucht. Und niemand bezahlt einen dafür, das JS deutlich kleiner zu machen. In der Regel geht es um zwei Dinge: Features, und wieviel Zeit (und damit Geld) es kostet, sie zu implementieren.

Ich habe trotzdem einen gewissen Stolz, und möchte dieses JS deutlich kleiner kriegen. Ich weiß noch nicht genau wie, aber es muss gehen. Privat kriege ich das ja auch hin (meist, weil ich überhaupt kein Javascript und keine CSS-Frameworks verwende). Und ich möchte hier ein Beispiel geben, wie man das in einem einfachen Fall machen kann. Doch zuerst ein kleiner Exkurs:

Exkurs: Ein Känguru-Running-Gag.

Ein running Gag in den Känguru-Büchern von Mark-Uwe Kling ist, dass sich das Känguru (und später Mark-Uwe Kling selbst) sich über Preise beschweren, indem sie einen Satz in der Form „N Euro? Das sind ja fast 2N D-Mark! 4N Ostmark! 20N Ostmark auf dem Schwarzmarkt“ von sich geben. Zum Beispiel:

20 Euro? Das sind ja fast 40 D-Mark! 80 Ostmark! 400 Ostmark auf dem Schwarzmarkt!

Irgendwann dieses Jahr wollte ich diesen Spruch auf Mastodon in einem Kommentar bringen, wusste aber nicht mehr, wie das Verhältnis von D-Mark zu Ostmark zu Ostmark auf dem Schwarzmarkt war. Also habe ich eine Internetsuche gemacht und bin unter anderem auf den Känguru-Rechner gestoßen. Ein kleine HTML-Seite, die nicht viel macht, außer bei der Eingabe einer der vier Werte die anderen automatisch auszurechnen. Der Link zu dem Blogpost geht leider ins Leere, weil sich dir URL geändert hat (sollte nicht passieren), aber den Blogpost gibt es noch unter einere leicht anderen URL, tatsächlich hat sich hier nur ein „a“ in der URL in ein „ä“ umgewandelt.

Warum erwähne ich das? Zum Einen finde ich diese Idee von so einem Rechner ganz lustig. Das Internet braucht solche kleinen Späße. Dann kann man diesen Känguru-Satz wunderbar auf Dateigrößen umformen und dabei dieselbe Empörung zum Ausdruck bringen (z.B. „1,5 Megabyte? Das sind ja fast zwei Megabyte! Sechs Megabyte unkomprimiert! Zwanzig Megabyte im Debug-Build!“). Insbesondere aber ist diese Seite vom Inhalt her winzig, bringt aber trotzdem 232 kiB auf die Waage.

Zum Vergleich: Die Startseite meines Blogs ist, vor der Veröffentlichung dieses Posts hier, knapp 225 kiB groß. Knapp 158 kiB davon sind Bilder, knapp 70 kiB davon HTML (der größte Teil davon tatsächlich der eigentliche Textinhalt des Blogs), der Rest fällt auf das CSS.

Der Kängururechner ist also nicht riesig im Verhältnis zu manch einer aufgeblähten Seite, aber deutlich größer als er sein müsste. Und er ist vom Funktionsumfang her ziemlich klein, was ihn zu einem perfekten Demonstrationsobjekt macht, wie man seine Website kleiner kriegen kann.

Disclaimer: Ich will niemanden bloßstellen

Das ist vielleicht wichtig zu sagen, bevor es jemand falsch versteht: Ich will nicht den Autor dieses Rechners bloßstellen. Das ist jemand, der als Hobbyprojekt vor Jahren mal eben diesen Rechner gebaut und ihn seitdem vermutlich nie mehr angefasst hat. Der Autor fordert in dem Blogpost selbst dazu auf, den Code zuverbessern. Der Autor hat mittlerweile ein mit Hugo generiertes Blog, das deutlich weniger Platz einnimmt als der Känguru-Rechner. Der Autor hat explizit Wert darauf gelegt, dass dieses Blog nur noch Resourcen von der eigenen Domain lädt, um den Datenschutz zu verbessern.

Soweit ich das erkennen kann ist der Autor ein cooler Mensch. Ich zeige hier die Verbesserungsmöglichkeiten des Kängururechners nicht auf, weil ich sagen will, dass er schlechte Arbeit gemacht hat, sondern weil ich den Kängururechner lustig finde und er so klein ist, dass man ihn gut als Beispiel nehmen kann.

Die Verkleinerung

Mein erster Gedanke war: „Ich kriege das locker auf unter 10 kiB“. Der zweite Gedanke war: „Mist. Nicht wenn ich die Custom-Schriftart behalten will“. Also, wo fangen wir an?

HTML-Fehler

Der erste Schritt ist keine Verkleinerung. Es gibt ein paar Syntaxfehler im HTML. Die behebe ich zuerst, damit ich einen stabilen Stand habe auf dem ich arbeiten kann. Da ist zunächst ein <noscript>-Tag im <head> Da die Hauptfunktion dieser Seite (die Berechnung der Zahlen) nur mit Javascript läuft, ist ein <noscript>-Tag eine gute Idee. Dieses hier ist aber im <head> und enthält ein <p> und ein <img>.

Beim genaueren Draufschauen ist das aber nur ein Zählpixel eines Tracking-Scripts des Tracking-Systems piwik. Immerhin kein Google Analytics, und es liegt auf dem Server des Autor selber. Mein uBlock Origin hat das aber sowieso geblockt, also nehme ich direkt einmal den ganzen piwik-Teil raus. Stattdessen füge ich ein tatsächlich hilfreiches <noscript>-Tag hinzu.

Weg mit Bootstrap!

Das ändert leider noch nicht viel an der Größe. Laut den Browsertools jedoch sind bootstrap.min.css (121 kiB) und jquery.min.js (28 kiB) für den gößten Teil des Bloats verantwortlich. Also weg damit! Zudem wird das auch noch von Drittsystemen geladen, ist also potentiell ein Angriffspunkt und eine Tracking-Möglichkeit.

Die Sache hat nur einen Haken: Damit ist ein Großteil des Layouts weg. Aber das ist nichts, was man mit ein bisschen CSS nicht selber hinkriegt. Dank fle ist das mittlerweile ziemlich einfach. Mein Ergebnis sieht dem Original recht ähnlich. Ich könnte es noch ähnlicher kriegen, aber was mir gerade wichtig ist: Es sieht vom Format her so aus wie vorher und es ist responsive, d.h. es verhält sich auf verschiedenen Bildschirmgrößen vernünftig. Dafür musste ich auch noch eine media-query einbauen, aber das war kein großes Problem.

Oh Mist, es funktioniert nicht mehr!

Mit Bootstrap habe ich auch jquery entfernt. Dummerweise funktioniert damit das Berechnungsscript nicht mehr. Naja, kein Problem. Dank modernem Javascript braucht man jquery eigentlich nicht mehr. Ich kann zum das hier

var euro = $(".number#euro");

ohne jquery so schreiben:

const euro = document.getElementById("euro");

Ich bin mir ziemlich sicher, das ging auch schon vor jquery so. JQuery fügt allerdings noch ein paar Komfortfunktionen hinzu. Anstatt also wie mit jquery so auf ein Event zu lauschen:

euro.blur(function() {
  const value = parse(euro);
  changeNumber("euro", value);
});

mache ich es so:

euro.addEventListener("blur", () => {
  const value = parse(euro);
  changeNumber("euro", value);
});

Ach warte: Ich muss auch noch Stellen wie euro.text() in euro.innerText umwandeln. Danach geht aber alles super.

Schriftarten

Jetzt sind wir schon auf weniger als 24 kiB runter. Für das bisschen CSS und Javascript, das wir selber schreiben mussten, echt ordentlich. Das HTML, CSS und JS von uns ist jetzt unter 5 kiB groß. Den Rest der Größe macht hauptsächlich die verwendete Schriftart aus: Indie Flower. Die wird momentan automatisch von Googlefonts geladen. Der erste Nachteil daran ist natürlich Google. Aber die Schrift steht unter der Open Font License und wir können sie auch von unserem eigenen Server ausliefern. Mit etwa 20 kiB ist die sogar recht schlank.

Ich stelle hier aber die Frage: brauchen wir die Schrift? Gerade bei geschäftlichen Seiten ist die Antwort oft „Ja, das ist unsere Corporate Design“. In vielen Fällen kann man jedoch „Nein“ sagen. So wie ich in diesem Fall. Ich lasse die Referenz auf die Schrift aber mal drin, für den Fall, dass jemand sie installiert hat. Sonst wird als Fallback halt die erstbeste cursive-Schrift verwendet:

font-family: 'Indie Flower', cursive;

Finishing touches

Jetzt nur noch den Footer anpassen: den Link auf den ursprünglichen Autor korrigieren, mein Repo dazu verlinken… oh, warte, ich habe noch kein Repo. Und mit dem Repo brauche ich noch eine README-Datei. Alles kein Problem. Repo erstellt.

Es gibt noch kleine Verbesserungen, die ich machen würde. Allen voran ein Favicon. Aber das gehört nicht hier hin. Schaut euch das Repo an, vielleicht kommt da noch etwas.

Fazit

Der verkleinerte Kängururechner ist jetzt auf meinem Server. Sieht ein bisschen anders aus als das Original, insbesondere weil die Schriftart anders ist, funktioniert aber genau so gut. Und ist unter 5 kiB groß, mit Kompression sogar noch weniger.

War das hier jetzt ein Tutorial? Hell no. Ich habe fast nicht gezeigt, was ich gemacht habe und wie. In dem Oben verlinkten Repo kann man sich die Änderungen allerdings anschauen, die ersten paar commits sind die Änderungen, die ich in diesem Post erwähnt habe.

Hilft mir das jetzt, die 1,5 MiB von meinem Job zu verkleinern? Auch nicht, dort sind die Probleme etwas anders gelagert.

Trotzdem, es war ein schöner Weg für mich, mich zu entspannen