— Teaser —
Ich mache nun schon eine ganze Weile Software im und für das Internet – seit 1999 um genau zu sein – und heute muss ich meinem Herzen mal Luft machen.
Liebe Juniors, liebe Seniors: Hört auf, mein Internet kaputtzumachen.
— Kleiner Exkurs – Wie alles begann —
Als ich anfing, professionell Software zu entwickeln (ich also Geld für etwas bekam, was ich gerne machte), da schrieb man das Jahr 1999 – es ist also schon eine Weile her. Damals™ war das Netz noch recht neu im Massenmarkt, es gab keine Androiden oder iPhones und Webseiten rief man auf dem Computer zu Hause mit einem Browser ab. Die Leitung in dieses neue Netz war eher langsam und kostete dazu in Deutschland sowohl einen monatlichen Festbetrag als auch noch einen Geldbetrag pro Zeiteinheit (meist ein paar Pfennige pro Minute, lies bei Wikipedia nochmal über die Deutsche Mark nach, wenn dir Pfennige nichts sagen). Kurzum: Zeit war ein doppelt treibender Faktor in diesem Internet. Zum einen war Zeit kritisch, weil die Leitung nicht so schnell war (ein winziger Bruchteil heutiger Technik) und zudem war es auch noch teuer, je länger man online war (Flatrates kamen erst später).
In diesem Umfeld bekam ich nun Kontakt mit dem Internet und lernte, wie die Technik zur Darstellung von Webseiten funktioniert, was das TCP/IP Protokoll ist (und warum dieses Protokoll so toll ist, bis heute) und was alles zwischen dem „ich drücke enter, nachdem ich die URL eingegeben habe“ und „der Browser ist endlich fertig, das Modem kann wieder aus“ so alles passiert – dies prägt mich bis heute. (Zur Erinnerung: Das Modem kann aus heißt, dass ab dann kein Geld mehr bezahlt werden musste … und es heißt auch, dass ab dann auch kein Internet mehr zur Verfügung stand; dies für die jüngeren unter euch).
Ich habe damals also – geprägt von Zeit- und Geldnot – viel gelernt, vor allem darüber, wie man die Informationen einer Webseite schnell und datenoptimiert an den Browser bringt. Generell war die Optimierung von Code an die Aspekte Schnelligkeit und Robustheit (beide sind gleichwertig zu betrachten) von großem Interesse und allgemeiner Usus, ähnlich wie heute Unit Testing zum „guten Ton“ gehört, so war es damals vor allem optimierter Code, der zum Handwerkszeug gehörte; erschien dein Code nicht optimiert, warf das kein gutes Licht auf dich und dein Können.
Das Resultat des Ganzen war Code, der schnell und stabil vom Server zum Browser gesendet wurde und dort komplett (und möglichst fehlerfrei) bis zum nächsten „Cache renew“ verbleiben konnte, damit die Leute sich deine Seite möglichst offline in Ruhe durchlesen konnten.
Wer jetzt ganz genau mitgelesen hat, der erkennt so manchen Kunstgriff, so manche Technik wieder, die heutzutage einen anderen Namen hat oder dem einfach ein neuer Anstrich gegeben wurde. Im Kern ist es aber nichts anderes ist als das, was schon vor über 25 Jahren zum guten Ton gehört hat. Begriffe wie „Client side caching“ kommen da vor, „Server side purging“, „Load balanced optimization“ und der Begriffe vieler sagen dem ein oder anderen bestimmt etwas.
— Paradigmen —
Ouch, ein schweres Wort, ein Wort zudem, bei dem sich 10 Entwickler im Raum nicht einigen können, was es denn genau bedeutet. In diesem Fall hier bedeutet es so etwas wie „verschriftlichte best practices“ im Sinne von: Wir haben damals viel ausprobiert, viel gelernt und haben versucht, dass, was sich als das Beste herauskristallisiert hat, niederzuschreiben, damit es die Leute nach uns nicht so schwer haben. Damit da etwas ist, woraus diese neuen Leute schneller lernen können und die alten Fehler nicht wieder machen (denn das spart Zeit, mit denen man wieder neue Wege beschreiten kann).
Eines dieser alten und fast vergessenen Paradigmen heißt abgekürzt YAGNI und ausgeschrieben steht es für „you aint gonna need it“ und bedeutet soviel wie „du brauchst das nicht“. Meistens wird dies zusammen mit einem anderen Paradigma gebraucht, dem KISS-Prinzip, was für „keep it simple stupid“ (hier kommt wahlweise ein Komma hin oder auch nicht, ist aber für den weiteren Verlauf nicht weiter wichtig). KISS soll einem sagen, dass man Dinge einfach halten soll, sprich: Gibt es mehrere Lösungswege für ein Problem, dann nimm das simplere. Klingt doch logisch, oder? Wer befasst sich gern mit schwierigen Lösungen, wenn es eine einfachere gibt, die genauso funktioniert. Der letzte Teil ist übrigens wichtig, denn zur Entscheidung, ob ich eine einfachere Lösung nehmen kann, bedarf es natürlich der Forderung an diese Lösung, dass diese bitte auch mein Problem lösen soll. Eine einfache Lösung, die mein Problem nicht oder nur zum Teil löst, ist nutzlos wie eine leere Rolle Toilettenpapier – theoretisch machbar, praktisch aber nicht zu empfehlen.
Bewaffnet mit dem Wissen um diese alten „best practices“ können wir nun einen Schritt weiter gehen.
— Wie Webseiten funktionieren —
Der technische geneigte Leser möge mir verzeihen, wenn ich in diesem Kapitel nur ganz grundsätzlich auf die Funktion des technischen Ablaufes eingehe, aber dieser reicht für ein grundsätzliches Verständnis zum Thema sicherlich aus, ohne den nicht-technischen Leser zu überfordern.
Prinzipiell funktioniert das Netz so, dass „ich“ als Benutzer eine Ressource bei einem Server anfordere und dieser mir eine Information zusendet, ob er mir diese ausliefern kann oder nicht (und dann auch, warum nicht). Im Weiteren gehen wir mal davon aus, dass wir keinen technischen Defekt haben und alle Ressourcen, die wir haben wollen, auch da sind, wo wir diese anfordern.
Ist eine Ressource vorhanden, dann liefert mir der Server eine Information dazu (200-OK) und meistens auch eine Antwort im „body“ welches dann die Ressource ist (ich sagte ja, ganz stark vereinfacht).
Im speziellen Fall einer Webseite können dies folgende Dinge sein:
– Die Seite selbst
– Zur Seite gehörende Dinge wie
— CSS
— Javascript
— Bilder
— sonstiges
Und eines ist noch gut zu wissen: Oben sprach ich von „ich“. Dieses „ich“ in diesem Fall der Browser. Dieser sendet eine Anfrage an den Server, der Antwortet dann und der Browser muss mit dem Ergebnis dann umgehen (und ggf. noch mehr Ressourcen nachladen).
Nur: Was macht der Browser denn da genau?
— Was der Browser spricht —
Der Browser, heutzutage ein Zwiespalt zwischen Chromium-basierten und dem Firefox, kann im Prinzip nicht viel mehr als es schon Browser in der alten Zeit konnten: Er kann HTML.
HTML – die „Hypertext Markup Language“ – ist das Grundgerüst jeder Webseite. Jeder. Wirklich.
Im Prinzip kann der Browser ohne HTML keine Webseite darstellen und egal auf welcher Seite im Netz du bist, du kannst ja mal in deinem Browser auf „Quelltext anzeigen“ gehen und siehst: Ja, HTML, definitiv.
Ok, der Browser kann auch noch ein paar Dinge mehr, dazu gehören z.B. Bilder anzeigen, Töne abspielen, Styles „verstehen“ und JavaScript interpretieren. Was braucht man sonst noch für eine Webseite, egal welche? Genau, nichts mehr. Das war’s. Alle Webseiten bestehen aus diesen Dingen.
Du brauchst ein Grundgerüst aus HTML, damit der Browser überhaupt etwas damit anfangen kann. In diesem HTML stehen dann diverse Dinge, zum Beispiel auch, ob der Browser noch etwas nachladen soll, nachdem er mit dem HTML interpretieren fertig ist. Dazu können Stylesheets gehören – die CSS Dateien – oder auch JavaScript, was eine Seite wieder dynamisch erscheinen lässt.
Aber die erste Sache, der Browser macht, ist HTML laden und interpretieren.
— Damals zu heute —
Die ersten Seiten im Netz bestanden nur aus HTML und dienten in erster Linie dem Informationsaustausch. Das Besondere an diesem Austausch war, dass man nicht nur Informationen darstellen konnte und sie „jeder“ (der es sich leisten konnte) abrufen konnte. Vielmehr war es die fantastische Möglichkeit, diese Informationen auch in Beziehung zueinander zu stellen. Das heißt, sprach man in einer Seite z.B. von Wikipedia, dann konnte man eine Beziehung zu einer anderen Seite herstellen, die dann diesen Begriff näher, tiefer, besser erklärte, so dass man seinen eigenen Kontext nicht immer wieder für Erklärungen verlassen musste. Eine tolle Sache, heute kennt man das als „Links“ auf Webseiten.
Ein wenig später kam dann der Wunsch auf, Seiten nicht mehr nur um ihrer Information wegen ins Netz zu stellen. Es kam – wie bei den meisten Dingen – auch darauf an, sie „schön“ zu präsentieren, was nach ein paar kurzen Irrungen und Wirrungen zu dem führte, was die meisten als CSS kennen. Die Möglichkeit, die Inhalte im HTML vom HTML getrennt gestalten. So sahen dann die Informationen ein wenig besser aus und konnten (manchmal, nicht immer) leichter gelesen werden.
Irgendwann zwischen „Wir haben das Internet erfunden“ und heute kam jemand auf die Idee, in diesem Internet doch auch dynamische Inhalte sehen zu wollen. Bis dahin war das Netz recht statisch. Es gab Seiten, Seiten standen in Beziehung zu anderen Seiten, aber im Prinzip hat sich eine Seite, war sie einmal online, nicht mehr geändert … zumindest nicht von selbst.
Die Technologie, die dynamische Inhalte ermöglichte, ist bis heute unter dem Namen „JavaScript“ bekannt (und nochmal: JavaScript hat nichts mit Java zu tun!!1!).
Diese Dinge, von erfahrener Hand respektvoll zusammen gefügt, ergaben zumeist informative Seiten, die überdies auch noch schön waren. Denkt man, in der Masse waren es meist blinkende Terrorwüsten ohne Inhalte, dagegen sind Cookie-Banner schon unaufdringlich – aber ich schweife ab, lassen wir uns die Illusion, dass die Webseiten mit HTML, CSS und JS gut funktionierten und ihren Sinn erfüllten.
Hier könnte die Geschichte nun zu Ende sein … wenn da nicht der „Ruf der Experten“ gekommen wäre.
— Berühmte Zitate —
Berühmte Zitate sind auch sowas wie „best practices“, allerdings nicht mit lehrender- sondern mit mahnender Funktion.
Besonders gut passt hier „Der Weg zur Hölle ist mit den besten Absichten gepflastert“, was uns so langsam in die Neuzeit des Netzes bringt.
— Soziale Medien als Motor —
Irgendwann nach 2010 (dem Datum des ersten iPhones und damit dem Massendurchbruch des mobilen Internets und damit dem Vormarsch sozialer Medien) kamen Entwickler der sozialen Medien auf Ideen, um Ihre Webseiten (nichts anderes ist ein soziales Medium technisch gesehen) schneller und effektiver an jedermann zu bekommen. Mobiles Internet war damals teuer (ähnlich wie das Internet generell ein paar Jahre vorher auch zu Hause) und damit die Leute die sozialen Medien auch unterwegs gern (und damit viel) benutzen, mussten die Seiten schnell geladen werden (auch das passt zu den Erfahrungen der Jahre vorher). Soziale Medien aber möchten auch viele Informationen an den Mann bringen, was zunächst dem Prinzip des „schnell“ eher entgegengesetzt ist. Wie bekommt man nun „schnell“ und „viel“ übereinander?
Das überlegten sich viele Leute, die Ergebnisse waren zumeist recht enttäuschend und alles andere als schnell (oder gar einfach). Dennoch, irgendwann hatten ein paar schlaue Menschen nicht nur die zündende Idee, sondern auch gleich die passende (und funktionierende) technische Lösung dafür: reaktive Webseiten. Du kennst das heute als „infinite scrolling“, d.h. du bist bei deinem Lieblingssocialnetzwork und kannst scrollen bis der Arzt kommt, es geht einfach immer weiter und weiter und weiter (auch als Doomscrolling bezeichnet). Der Trick hierbei ist, dass die Inhalte nicht im initialen Requests deines Browser zu finden sind, sondern die Dinge werden „on the fly“ immer dann geladen, wenn du am Ende der geladenen Daten bist. Heute geht das recht zügig, so dass der normale Netznutzer auch im mobilen Falle nichts oder nicht viel davon mitbekommt.
Und damit fängt das Problem so langsam an, konkret zu werden.
— Die „Lösung“ —
Massenhaft Daten dynamisch ohne Seitenwechsel nachzuladen bedeutet, dass wir mit den Standardmitteln nicht weit kommen. Daten nachladen ohne eine neue Seite zu laden bedeutet, dass wir die Daten per JavaScript nachladen müssen. An und für sich ist das nichts neues und auch, je nach Einzelfall, auch nicht per se schlecht. Es gibt durchaus Szenarien, wo das Sinn macht und auch sinnvoll ist. Das Problem eskalierte allerdings anders.
Ein großes soziales Netzwerk „erfand“ (nicht wirklich, wir vereinfachen aber mal) ein JavaScript-Framework, dessen Grundgerüst nicht mehr die Ergänzung von HTML darstellte, vielmehr begreift sich dieses Framework als Grundgerüst selbst, so dass sämtliche Arbeiten zur Darstellung der Homepage nicht mehr per HTML (und CSS und JS) getätigt werden, sondern samt und sonders in JS selbst durchgeführt werden. Für den jungen und unerfahrenen Entwickler bietet das den „Vorteil“, dass er „seine“ eine Sprache nicht verlassen muss und alles komplett „ohne Stilbruch“ aus einem Guss erledigen kann. Kein Witz, dies ist wirklich eine der Argumentationen für diese Vorgehensweise und dummerweise glauben bis heute viele Entwickler, dass das eine gute Sache wäre.
— Der Stand der Dinge —
Kommen wir nun zu den Details und damit dahin, wo es schmerzt. Nicht im Sinne von „es funktioniert nicht“, sondern im Sinne von „warum glaubt ihr, dass das eine gute Idee ist“. Kurzum, sehen wir die „Lösung“ mal an.
Der aktuelle Stand der Dinge ist der, dass viele junge Entwickler damit groß werden – und auch so ausgebildet werden -, dass alles in JS erledigt werden kann, was dann oft zu dem Irrglauben führt, dass auch alles in JS erledigt werden muss und JS-Frameworks sozusagen alternativlos sind.
Aber was passiert eigentlich bei diesen Frameworks?
Bauen wir uns doch mal ein gedankliches Beispiel: Lass uns eine Seite für eine Arztpraxis bauen, vielmehr, lass uns zwei Seiten bauen, gleiches Layout, gleiche Funktionen, das eine mit einem JS Framework, das andere klassisch.
Beim JS-Framework brauchen wir gar keines konkret heranziehen, da der Funktionskern prinzipiell gleich ist. Von daher können wir einen Pseudo-Funktionsansatz darlegen, der zur Veranschaulichung auch völlig ausreichend ist.
— Der Framework Ansatz —
Natürlich benötigen wir zunächst mal ein installiertes NodeJS nebst npm. Dann brauchen wir entsprechend natürlich auch unser geliebtes JS-Framework (hier Name einfügen) und das zieht sich dann auch gleich mal alle seine Abhängigkeiten in Form diverser JS-Pakete ran. Dabei benötigt natürlich auch jedes Paket wieder seine eigene Abhängigkeiten von anderen Paketen, die npm natürlich auch gern für uns auflöst, runterlädt und an seinen Platz in den `node-modules` Ordner legt. Allein die Vanilla für das Framework wiegt bereits jetzt eine Menge.
Dann müssen wir natürlich auch die Seite selbst bauen, d.h. wir müssen routing einstellen, (Pseudo-)Klassen anlegen, Komponenten registrieren und benutzen, alles so verpacken, dass es das Framework auch versteht und dann am Ende die Inhalte der Seite anlegen.
Anschließend laden wir alles auf unseren Webserver, stellen den entsprechend so ein, dass der auch korrekt in das Framework routet und rufen dann die Seite auf.
Wenn man sich jetzt den Spaß macht und in den Browser eigenen Entwicklertools nachsieht (drück doch mal F12, wenn du nicht weißt, wovon ich rede), dann nimmt sich der Aufruf meist recht viel Zeit und ist auch recht groß. Du siehst das ganz unten in den Entwicklertools bei den „Netzwerkanalysen“ wo steht „xyz Anfragen, xyz übertragen, Beendet: xyz ms“.
Merk dir diese Zahlen mal, sowohl was die Anzahl der Requests angeht, als auch die Größe der übertragenen Daten.
Der Kern des Ganzen, warum ich diesen Ansatz kritisiere, ist der, dass zunächst einmal Tonnen von Daten Clientseitig durch ein Framework geroutet werden, um dann am Ende doch wieder zu einer kleinen Arztpraxis-HTML-Seite zusammenzufallen. Der Aufwand, um hier zum Ergebnis zu kommen, ist recht hoch, gleichwohl der Nutzen doch eher überschaubar bleibt. Möge mir jemand das Buch der Erkenntnis reichen, den bisher sehe ich da keinen Vorteil.
— Der klassische Ansatz —
Wir erstellen Seiten+1 Dateien, eine ist für das CSS, die anderen sind die eigentlichen Seiten. Da bauen wir einfach die Seiten, die wir brauchen und nennen die „xyz.html“, die zusätzliche nennen wir „xyz.css“ und die ist nur für das CSS. Okay, wir könnten noch eine machen, eine „xyz.js“, aber mal ehrlich, warum? Das wird eine Arztseite, dynamisch ist anders.
Wenn wir fertig sind, laden wir die alle auf den Server und sind fertig – html und css können alle Webserver per Default ausliefern, dafür sind die gebaut worden *zwinkersmily*.
Auch jetzt schauen wir nochmal in den Netzwerkanalysen nach und siehe da, exakt Seiten+1 (oder +2, je nachdem ob wir eine js mitliefern oder nicht) Requests wurden gemacht. Ich gehe fast jede Wette ein, dass die Größe und die benötigte Zeit für das Abrufen der Seite wesentlich kleiner sind als mit dem anderen Ansatz.
— Von Hämmern und Nägeln —
„When all you have is a hammer, everything looks like a nail!“ … das ist ein schlauer Spruch, den man sich tief im Gehirn verankern sollte. Du bist ein Junior, du kennst dich mit JS aus. Okay, aber warum kennst du dich nur mit JS aus? Weißt du, dass alle JS-Frameworks am Ende auch nur HTML auswerfen? Was anderes kann dein Browser einfach nicht darstellen. Auch Electron nicht (ist auch nur ein gemappter Chromium-Browser). Die wollen alle nur HTML haben.
Und nun mal eine Frage: Warum gibst du ihm nicht einfach HTML?
Es mag sicherlich ganz toll sein, wenn man einen Hammer hat. Damit kann man wunderbar Nägel in die Wand hämmern. Wenn du allerdings nur einen Hammer hast, dann fängst du auch an, Schrauben in die Wand zu kloppen (oder wer-weiß-wohin noch) und oberflächlich betrachtet funktioniert das auch …. zunächst. Aber der Teil, den du nicht siehst, der erhält durch unsachgemäße Benutzung Schäden (in dem Beispiel: Der Dübel wird zertrümmert, die Schraube zerstört). Und offenbar ist das ja auch erst einmal in Ordnung, weil: Das kleine leichte Bild, was du da aufhängst, das hängt doch. Ergo: Funktioniert.
Was bei deinem kleinen Bild noch ok zu sein vermag, das hält allerdings die Analogie zur Softwareentwicklung nicht mehr aus. Sicher mag dein Projekt im kleinen Rahmen (lies: auf deinem Rechner oder kurz nach dem Live-Start) noch funktionieren, was passiert aber, wenn dein Projekt plötzlich ein Erfolg wird? Von jetzt auf gleich strömen nicht mehr 2 Besucher pro Stunde deine Seite, sondern 20.000 pro Minute. Hält dein Projekt das aus? Die Schraube in der Wand wird mit Sicherheit keinen Elefanten aushalten, so kaputt wie die innen drin ist.
Jetzt sagt so mancher „meh, das ist unrealistisch“. Ist es das? Ist es nicht das, was sich alle Entwickler wünschen, dass „dein“ Projekt wie eine Bombe einschlägt und erfolgreich wird? Ich wünsch mir das jedes Mal und aus dem Grund bereite ich mich auch darauf vor, dass es mal so weit kommt. Ich betrachte als verantwortungsvoller Entwickler nicht nur den normalen „alles ist rosa“ Weg, ich betrachte vor allen Dingen die aus der Mathematik bekannten Grenzwerte, die Randbereiche, die „Roten Zonen“, die Kehrpunkte, kurzum: Ich bin da, wo es weh tut, in der roten Zone.
Warum? Ganz einfach: Wenn es in der roten Zone funktioniert, dann funktioniert es überall!
Warum die ganzen Umwege über Frameworks, Komponenten, Abhängigkeiten von eher fragwürdigen 3rd Party Librarys (wann wurden die zuletzt aktualisiert? Welche Sicherheitslücken haben die eigentlich?).
— Security —
Apropos Security!
Ich selbst baue nicht nur beruflich Webprojekte, ich baue die auch im Privaten, zum Teil auch für das Ehrenamt. Mein Anspruch an meine privaten Projekte ist nicht anders als der Anspruch für die beruflichen Projekte. Ergo untersuche ich den Code für meine Projekte auch (nicht nur, aber auch) auf die Sicherheit. Dazu gibt es Tools und Anbieter, die einen dabei unterstützen (verlass dich aber nicht nur auf andere, denkt auch selbst).
Meine Web-Projekte basieren zumeist auf dem TALL-Stack, d.h. im Kern ist es PHP auf der einen und JS auf der anderen Seite. Was mir nun auffällt ist, dass ich wesentlich (!) mehr Meldungen zu Sicherheitsproblemen in den JS-Teilen bekomme als in den PHP Teilen. Damit meine ich in beiden Fällen die jeweiligen 3rd Party Librarys, die zwangsläufig sowohl bei PHP als auch bei JS installiert werden. Es ist erschreckend, dass sich da eine Quote von 17:1 rauskristallisiert (nochmal für Juniors: auf 17 Sicherheitsmeldungen zu JS kommt eine für PHP, Tendenz eher steigend auf Seiten JS).
— Fazit —
Eingangs erwähnte ich bereits die best practices aus grauer Vorzeit, „YAGNI“ und „KISS“. Meine Beobachtung ist aber, dass diese Paradigmen entweder nicht mehr beachtet werden oder deren Existenz schlicht unbekannt ist.
Wenn die dir unbekannt waren, dann freut es mich, dass ich es dir näher bringen konnte. Du kannst dich gern weiter in diese Prinzipien vertiefen und diese verinnerlichen, es wird dazu beitragen, aus dir einen besseren Entwickler zu machen.
Wenn es allerdings nicht beachtet wird, dann heißt dies ja, dass diese Paradigmen durchaus bekannt sind und schlicht aus gottgegebener Selbstherrlichkeit missachtet werden. Aber: Warum? Machst du irgendwas besser, weil du mehr Dinge auf das Problem wirfst, ohne es besser zu lösen? Wahrscheinlich nicht. Mein Eindruck bei dieser Sparte („ich ignoriere mal dieses alte Zeug, das ist alt, heute machen alle JS, basst scho“) ist leider, dass viele zum einen gar nicht den Überblick und damit das Wissen haben, was da eigentlich im Hintergrund passiert und zum anderen nur sehr wenige bereit sind, sich dem „alle machen das“ entgegenzustellen.
In meinem Kopf geht dann immer ein Schild mit einem sehr sinnigen Spruch hoch:
„Fresst mehr Scheiße, Milliarden Fliegen können sich nicht irren!“
Soviel zur Weisheit der Masse 😉
Mein persönlicher Anspruch ist, dass ich das immer das „limes(beste Projekt)“ baue und dazu gehört auch, dass ich mir zuerst die Aufgabenstellung anhöre und erst dann entscheide, mit welchen Technologien man das wohl lösen könnte. Mein Werkzeugkasten umfasst mehr als nur eine Sprache und mehr als nur ein Framework und dies alles aus Jahren der Erfahrung, des Scheiterns und Verzweifeln, des Wegwerfen und „Machen wir die Nacht durch und schreiben es neu“-coden.
Aspekte wie Sicherheit, Robustheit und Schnelligkeit (alle sind gleichwertig) haben bei mir immer Vorrang vor irgendeinem „das geht noch hübscher, wenn wir library xyz noch requiren“ Ansatz. Zuerst muss es funktionieren, es muss stabil sein, schnell und sicher.
Hübsch kommt dann und CSS mit HTML kann in der Regel bereits 90% deines JS-Frameworks abdecken, man sollte nur mal die Doku von HTML komplett lesen.
Ständiges Hinterfragen deines Wissens wird dazu beitragen, dass du ein besserer Entwickler wirst; ein Leitstrahl kann für dich derselbe Satz sein wie für mich: „scio me nihil scire“.