© Dukesn/ Shutterstock.com
Von Bundlers und der Komplexität in JavaScript- Projekten

Zurück auf den Boden der Tatsachen


JavaScript-Projekte sind komplex, wobei viele der Probleme hausgemacht sind. Dieser Artikel geht einigen Problemen sowie ihren Ursachen auf den Grund. Er zeigt, wie mit Hilfe moderner Werkzeuge und Standards, etwa Snowpack und ESM, ein Weg aus der Komplexitätsfalle gefunden werden kann.

Gestatten Sie mir eine kleine, zugegebenermaßen etwas provokante Frage? Wie werden heutzutage moderne Webanwendungen gebaut? Ganz richtig: Die Standards HTML5, CSS und JavaScript machen es möglich. Mit Hilfe von HTML geben wir die Strukturen unserer Anwendung vor und legen Inhalte fest. CSS sorgt für ein gutes Aussehen, ein passendes Layout sowie ein einheitliches Styling und mit JavaScript – pardon, ECMAScript – implementieren wir schließlich das Verhalten unserer Anwendung und erwecken sie somit zum Leben. Das klingt alles ganz simpel und einleuchtend, aber genau hier liegt das Problem.

Das alles ist viel zu einfach! Die moderne Entwicklerin beziehungsweise der moderne Entwickler von heute neigt ganz selbstverständlich dazu, viele unterschiedliche, ja bessere und ausgereiftere, aber vor allem professionellere Werkzeuge für seine Arbeit einzusetzen! Machen ja alle so. Zunächst einmal brauchen wir eine „richtige“ Programmiersprache, nicht dieses halbgare JavaScript. Wir ersetzen JavaScript/ECMAScript also durch TypeScript und schon haben wir eine aktuell sehr angesagte Sprache im Projekt. Die kann alles, was das Herz begehrt. Wir können wahlweise objektorientiert oder funktional programmieren, haben Typensicherheit und auch sonst ist alles an Bord, was man heute eben braucht. Im Bereich der Strukturen und der Inhalte, sorry, da reicht uns dieses schlichte HTML natürlich auch nicht mehr aus. HTML kann doch, wie JavaScript, nur die Basistechnologie sein. Auf HTML aufsetzend wollen wir ein Framework benutzen – machen ja schließlich alle so – und wir wollen eigene, wiederverwendbare HTML-Komponenten bauen. HTML läuft also nur noch unten drunter, oben drüber nutzen wir React oder Vue, um Struktur durch die Realisierung einer sogenannten komponentenbasierten Architektur zu bekommen. Ja, und was ist mit diesem CSS? Ganz ehrlich: Diese komische Syntax kann doch keiner lesen, da braucht man also schon einen sogenannten CSS-Präprozessor damit wir CSS auch in kurzer und einfacher Form schreiben können. Die Möglichkeiten hier sind reichhaltig. Wir können CSS beispielsweise durch Sass ersetzen, um nur ein Beispiel zu nennen.

Die Komplexität steigt

Die bisher genannten Werkzeuge ergeben bestimmt Sinn und haben eine Daseinsberechtigung, da sie uns die Programmierarbeit erleichtern und uns somit effizienter werden lassen. Doch – und das ist wichtig zu verstehen – die Komplexität steigt. Und sie steigt noch weiter: Als wäre bis hierher noch nicht alles kompliziert genug, neigen wir dazu, für jedes Problem und für jede zusätzliche Anforderung, die wir haben, noch weitere Bibliotheken zu suchen und einzusetzen. Diese sind schließlich da, also muss nicht selbst programmiert werden. Ein echter Mehrwert? Wenn man sich die Webprojekte verschiedenster Unternehmen auf Basis von HTML5, CSS und JavaScript so anschaut, zieht sich dieses Prinzip durch wie ein roter Faden. Überall findet man mehr oder weniger viele Abhängigkeiten: Es wird eine Bibliothek zur tabellarischen Darstellung von Daten benötigt? Schon hat man zum Beispiel AGGrid im Projekt. Da typische Softwareentwickler üblicherweise keine Designer sind, wird selten das komplette Layout einer Webanwendung selbst in CSS oder Sass gestaltet. Es wird stattdessen eine Designsprache eingebunden, beispielsweise Ant Design oder Material Design. Das sind dann Sass/CSS-Vorlagen, mit denen sich eine Webanwendung in ein einheitliches, professionelles Design bringen lässt. Ant Design und viele weitere Werkzeuge seiner Art bringen zusätzlich noch eine mehr oder weniger große Anzahl vorgefertigter Oberflächenkomponenten mit, die man direkt mit React oder Vue verwenden kann. Das ergibt alles Sinn und wird gerne genutzt. Für die Verarbeitung von Datum und Zeit ist Moment.js recht schnell eingebunden, zum Aufrufen von Web-APIs gehört Axios zum guten Ton und Lodash ist sowieso in fast jedem Webprojekt zu finden, das etwas auf sich hält. Von den vielen kleinen Hilfsroutinen, die man so erhält, will man profitieren. Sie merken hoffentlich schon, worauf ich hinauswill. Mehr Abhängigkeiten im Projekt bedeutet einen zusätzlichen Grad an Vielschichtigkeit. Und das führt uns zum nächsten Problem: All diese Bibliotheken und Zusatzgewerke einfach so ins eigene Projekt einbauen, das funktioniert in vielen Fällen erstmal nicht ohne Weiteres. Nehmen wir zum Beispiel Lodash. Das direkte Einbinden und Aufrufen von Hilfsfunktionen aus dieser Entwicklerbibliothek in ein JavaScript/TypeScript-Projekt wird Probleme bereiten. Warum ist das so? Es liegt an der Art und Weise, wie JavaScript-Programme sich zusammensetzen und zum Browser ausgeliefert werden.

Modulsysteme

Für die sogenannte Modularisierung gab es lange Zeit keinen Standard. Den gibt es erst seit jüngerer Zeit und er heißt ECMAScript Modules oder kurz ESM. Da es ESM und damit eine offizielle Lösung lange Zeit nicht gab, haben sich verschiedene Unternehmen, Organisationen sowie Entwickler eigene Gedanken gemacht, wie so ein Modulsystem aussehen könnte, und es sind dabei einige, bis heute sehr populäre Lösungen entstanden. Im Rahmen des bekannten Projekts RequireJS hat das weithin bekannte AMD-Format das Licht der Welt erblickt. AMD steht für Asynchronous Module Definition. Ziel der Entwicklung war es, den schmerzlich vermissten Standard zu definieren, um Programmteile asynchron nachladen und einbinden zu können. CommonJS ist ein weiteres Modulsystem, das in die gleiche Kerbe schlägt und sich bis heute hält. Es wurde von den Entwicklern der JavaScript-Laufzeitumgebung Node erfunden und ist somit integraler Bestandteil einer jeden Node-Installation. Wichtig ist dabei, zu verstehen, dass Node ursprünglich zum Ausführen von JavaScript-Anwendungen auf Servern gedacht war, folglich ist CommonJS eigentlich gar nicht wirklich für den Einsatz im Browser vorgesehen. Aus diesem Grund bekommt man beim Einbinden von Bibliotheken, die im CommonJS-Format vorliegen, oftmals merkwürdige Fehlermeldungen wie Abbildung 1 zeigt.

teufel_bundlers_1.tif_fmt1.jpgAbb. 1: Fehlermeldung beim Einbinden einer Bibliothek

Der Befehl require ist ein Konstrukt, das eben nur im Node-Umfeld bekannt ist und dafür sorgt, dass ein Modul geladen wird. Das bedeutet, dass Bibliotheken, die auf CommonJS basieren, definitiv nicht ohne Weiteres im Browser laufen. Um solche Bibliotheken im Browser dennoch betriebsfähig zu machen, muss im Zusammenhang mit der Entwicklung also noch eine Konvertierung, eine Anpassung des Quellcodes stattfinden. Hier wird der proprietäre Anteil des Modulsystems durch im Browser lauffähigen Code ersetzt. Das ist einer der Gründe, warum wir Bundlers wie webpack, Rollup oder Parcel einsetzen. Die meisten JavaScript-Bibliotheken setzen bis heute auf CommonJS, weil zu dem Zeitpunkt, zu dem die Projekte gestartet wurden, dieses Modulsystem die beste Lösung war. Ganz anders verhalten sich hier Bibliotheken, die schon im neueren Modulstandard ESM vorliegen. Diese sind out of the box im Browser lauffähig. Der Befehl require wird durch import ersetzt und es ist keine Veränderung des ...

Neugierig geworden? Wir haben diese Angebote für dich:

Angebote für Gewinner-Teams

Wir bieten Lizenz-Lösungen für Teams jeder Größe: Finden Sie heraus, welche Lösung am besten zu Ihnen passt.

Das Library-Modell:
IP-Zugang

Das Company-Modell:
Domain-Zugang