Noch ein JavaScript Framework

Avatar of Jay Hoffmann
Jay Hoffmann am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

Am 6. März 2018 wurde ein neuer Bug im offiziellen Bug-Tracker des Mozilla Firefox Browsers gemeldet. Ein Entwickler hatte ein Problem in der Nightly-Version von Mozilla bemerkt. Der Bericht besagte, dass ein Wettervorhersage-Widget für 14 Tage, das üblicherweise auf einer deutschen Website zu finden war, plötzlich kaputtgegangen und verschwunden war. Nichts auf der Website hatte sich geändert, also musste das Problem bei Firefox liegen.

Bug 1443630: Implementing array.prototype.flatten broke MooTools' version of it.
Ein Screenshot des bei Mozilla eingereichten Bug-Reports.

Das Problem, so stellte der Entwickler in seinem Bericht fest, schien auf die Verwendung der JavaScript-Bibliothek MooTools durch die Website zurückzuführen zu sein.

Auf den ersten Blick schien der Bug ziemlich Routine zu sein, höchstwahrscheinlich ein kleines Problem irgendwo im Code der Website oder ein seltsamer Zufall. Nach nur wenigen Stunden wurde jedoch klar, dass die Einsätze für diesen einen speziellen Bug weitaus gravierender waren, als irgendjemand hätte ahnen können. Wenn Firefox diese Version seines Browsers so veröffentlichen würde, liefen sie Gefahr, eine unbekannte, aber dennoch vorhersagbar recht große Anzahl von Websites auf einmal zu beschädigen. Warum das so ist, hat alles mit der Art und Weise zu tun, wie MooTools entwickelt wurde, wovon es beeinflusst wurde und zu welchem Zeitpunkt es veröffentlicht wurde. Um das Problem wirklich zu verstehen, müssen wir ganz am Anfang beginnen.

Am Anfang

Zuerst gab es reines JavaScript. 1995 von einem Team bei Netscape veröffentlicht, begann JavaScript in den späten 90er Jahren im allgemeinen Gebrauch Fuß zu fassen. JavaScript gab Webentwicklern, die mit HTML arbeiteten, einen Schub, indem es ihnen ermöglichte, Dinge dynamisch zu verschieben, Inhalte leicht zu animieren und Zähler, Aktienkurse, Wetter-Widgets und allerlei interaktive Elemente zu Websites hinzuzufügen.

Bis 2005 war die JavaScript-Entwicklung immer komplexer geworden. Dies wurde durch die Verwendung einer Technik ausgelöst, die wir als Asynchronous JavaScript and XML (Ajax) kennen, ein Muster, das heutzutage für jeden, der eine Website mehr als nur zum Lesen von Inhalten nutzt, wahrscheinlich vertraut ist. Ajax öffnete die Tür für anwendungsähnliche Funktionalitäten, die nativ im Web verfügbar waren, und ermöglichte die Veröffentlichung von Projekten wie Google Maps und Gmail. Der Begriff „Web 2.0“ wurde beiläufig eingeführt, um diese neue Ära der dynamischen, benutzerorientierten und interaktiven Webentwicklung zu beschreiben. Alles dank JavaScript.

Es war speziell Ajax, zu dem Sam Stephenson in den frühen Jahren des Jahrhunderts immer wieder zurückkehrte. Stephenson war ein regelmäßiger Mitwirkender an Ruby on Rails und stieß immer wieder auf die gleichen Probleme, wenn er versuchte, mit JavaScript mithilfe eines ziemlich gängigen Ajax-Codes eine Verbindung zu Rails herzustellen. Insbesondere schrieb er jedes Mal den gleichen Basissatz an Code, wenn er ein neues Projekt startete. Also schrieb er ein paar hundert Zeilen Code, die die Ajax-Verbindungen mit Rails vereinfachten und die er in all seine Projekte portieren konnte. Innerhalb weniger Monate wurden aus hundert Zeilen viele mehr, und Prototype, eines der frühesten Beispiele für ein vollständiges JavaScript-Framework, wurde offiziell veröffentlicht.

A screenshot of the Prototype website.
Eine frühe Version der Prototype-Website, die die Benutzerfreundlichkeit und die klassenbasierte Struktur hervorhebt.

JavaScript erweitern

Ruby nutzt Klassenvererbung, die sich eher für objektorientierte Entwicklung eignet. Wenn Sie nicht wissen, was das bedeutet, müssen Sie nur wissen, dass es ein wenig im Gegensatz zu der Art und Weise steht, wie JavaScript aufgebaut wurde. JavaScript stützt sich stattdessen auf das, was als prototypische Vererbung bekannt ist. Was bedeutet das? Es bedeutet, dass alles in JavaScript unter Verwendung des Basisobjekts als Prototyp erweitert werden kann. *Alles*. Sogar native Objektprototypen wie String oder Array. Tatsächlich fügen Browser neue Funktionen und Features zu JavaScript hinzu, indem sie oft diese besondere Sprachfunktion nutzen. Daher hat Stephenson seiner Bibliothek den Namen Prototype gegeben.

Die Quintessenz ist, dass prototypische Vererbung JavaScript von Natur aus fehlerverzeihend und leicht erweiterbar macht. Es ist im Grunde für jeden Entwickler möglich, auf der Kern-JavaScript-Bibliothek in seinem eigenen Code aufzubauen. Dies ist in vielen anderen Programmiersprachen nicht möglich, aber JavaScript war schon immer ein Ausreißer in Bezug auf seinen Ansatz, einer viel größeren, domänenübergreifenden Entwicklerbasis entgegenzukommen.

All dies bedeutet, dass Stephenson zwei Dinge getan hat, als er Prototype schrieb. Das erste war, ein paar Helfer hinzuzufügen, die objektorientierten Entwicklern wie ihm ermöglichten, mit JavaScript in einer vertrauten Codestruktur zu arbeiten. Das zweite und hier weitaus wichtigere ist, dass er begann, bestehendes JavaScript zu erweitern, um Funktionen hinzuzufügen, die für einen späteren Zeitpunkt *geplant*, aber noch nicht *implementiert* waren. Ein gutes Beispiel dafür war die Funktion document.getElementByClassName, eine leicht umbenannte Version einer Funktion, die erst etwa 2008 in JavaScript eingeführt wurde. Prototype erlaubte Ihnen, sie bereits 2006 zu verwenden. Die Bibliothek war im Grunde eine Wunschliste von Funktionen, deren Implementierung von Browsern in der Zukunft versprochen wurde. Prototype gab diesen Entwicklern einen Vorsprung und machte es viel einfacher, die einfachen Dinge zu tun, die sie jeden Tag tun mussten.

Prototype durchlief einige Iterationen in schneller Folge und gewann an Fahrt, nachdem es kurz nach seiner Veröffentlichung standardmäßig in allen Ruby on Rails-Installationen enthalten war. Auf dem Weg legte Prototype den Grundstein für praktisch jedes Framework, das danach kam. Zum Beispiel war es das erste, das das Dollarzeichen ($) als Kurzschreibweise für die Auswahl von Objekten in JavaScript verwendete. Es schrieb Code, der, in seinen eigenen Worten, „selbsterklärend“ war, was bedeutete, dass die Dokumentation spärlich war und das Erlernen der Bibliothek das Eintauchen in den Code bedeutete, eine Praxis, die heutzutage mehr oder weniger üblich ist. Und vielleicht am wichtigsten ist, dass es die Schwierigkeit beseitigte, Code in allen Browsern zum Laufen zu bringen, eine fast herkulische Aufgabe in Zeiten, in denen sich die Browser selbst auf sehr wenig einigen konnten. Prototype funktionierte einfach in jedem damals modernen Browser.

Prototype hatte seine faire Konkurrenz von anderen Bibliotheken wie base2, die die objektorientierten Teile von Prototype aufgriffen und sie in eine kompaktere Version auslagerten. Aber der größte Konkurrent der Bibliothek kam, als John Resig beschloss, sein eigenes Pferd ins Rennen zu schicken. Resig war besonders an dem letzten Punkt interessiert, dem Teil mit dem Code, der in allen Browsern funktioniert. Er begann 2005 an einer anderen Interpretation dieser Idee zu arbeiten und enthüllte schließlich im Januar 2006 auf dem Barcamp in New York eine eigene Bibliothek.

Sie hieß jQuery.

Neue Welle JavaScript

jQuery wurde unter dem Slogan „New Wave Javascript“ veröffentlicht, ein seltsamer Titel angesichts dessen, wie viel Resig von Prototype übernommen hatte. Alles, von der Syntax bis zu seinen Werkzeugen für die Arbeit mit Ajax – sogar die Verwendung eines Dollarzeichens als Selektor – wurde von Prototype auf jQuery übertragen. Aber es wurde nicht New Wave JavaScript genannt, weil es originell war. Es wurde New Wave JavaScript genannt, weil es neu war.

jQuery: New Wave JavaScript. jQuery is a new type of JavaScript library. jQuery is designed to change the way that you write JavaScript.
„New Wave“ JavaScript

Der größte Unterschied von jQuery zu Prototype und seinen Verwandten bestand darin, dass es nicht die bestehenden und zukünftigen JavaScript-Funktionen oder Objekt-Primitive erweiterte. Stattdessen schuf es brandneue Features, die alle mit einer einzigartigen API zusammengestellt wurden, die *auf* dem aufbaute, was bereits in JavaScript existierte. Wie Prototype bot jQuery viele Möglichkeiten zur Interaktion mit Webseiten, wie z. B. die Auswahl und Bewegung von Elementen, die Verbindung zu Servern und die Schaffung von schnellen und dynamischen Seiten (obwohl es die objektorientierten Neigungen seines Vorgängers vermissen ließ). Entscheidend war jedoch, dass all dies mit *neuem* Code geschah. Neue Funktionen, neue Syntax, neue APIs, daher eine neue Welle der Entwicklung. Man musste die „jQuery-Art“ der Dinge lernen, aber sobald man es tat, konnte man sich tonnes of time mit all den Dingen sparen, die jQuery viel einfacher gemacht hat. Es ermöglichte sogar erweiterbare Plugins, was bedeutete, dass andere Entwickler coole, neue Dinge darauf aufbauen konnten.

MooTools

Das mag klein klingen, aber dieser leichte Paradigmenwechsel war wirklich gewaltig. Ein so seismischer Wandel erforderte eine Reaktion, eine Reaktion, die zufällig im folgenden Jahr, 2007, kam, als Valerio Proietti sich von einer anderen Bibliothek völlig frustriert fand. Die Bibliothek hieß script.aculo.us und half Entwicklern bei Seitenübergängen und Animationen. So sehr er sich auch bemühte, Proietti konnte script.aculo.us einfach nicht dazu bringen, das zu tun, was er tun wollte, also (wie viele Entwickler in seiner Position es in der Vergangenheit getan haben) beschloss er, seine eigene Version neu zu schreiben. Als objektorientierter Entwickler selbst war er bereits ein großer Fan von Prototype, also basierte er seine erste Version auf den Grundprinzipien der Bibliothek. Er versuchte sogar, mit seinem ersten Namensversuch von seinem Erfolg zu profitieren: prototype.lite.js. Ein paar Monate und viele neue Funktionen später verwandelte Proietti dies in MooTools.

Wie Prototype verwendete MooTools eine objektorientierte Programmiermethodik und prototypische Vererbung, um die Funktionalität von Kern-JavaScript zu erweitern. Tatsächlich ging es bei den meisten MooTools darum, den eingebauten Prototypen (d. h. String, Array) neue Funktionen hinzuzufügen. Ein Großteil dessen, was MooTools hinzufügte, stand auf der JavaScript-Roadmap zur Aufnahme in Browser zu einem bestimmten Zeitpunkt in der Zukunft; die Bibliothek sollte die Lücke in der Zwischenzeit füllen. Die allgemeine Idee war, dass sie, sobald eine Funktion endlich in den Browsern landete, einfach ihren eigenen Code aktualisieren würden, um sie anzupassen. Webdesigner und Entwickler mochten MooTools, weil es leistungsstark und einfach zu bedienen war und ihnen das Gefühl gab, in der Zukunft zu programmieren.

MooTools is a compact, modular, Object-oriented JavaScript framework designed to make writing extensible and compatible code easier and faster.
MooTools: Objektorientiert, entwicklerfreundlich

Es gab auch viel von jQuery. Wie jQuery glättete MooTools Inkonsistenzen und Fehler in den verschiedenen Browsern auf dem Markt und bot schnelle und einfache Möglichkeiten, Übergänge hinzuzufügen, Serveranfragen zu stellen und Webseiten dynamisch zu manipulieren. Bis zur Veröffentlichung von MooTools war die jQuery-Syntax mehr oder weniger zum Standard geworden, und MooTools würde die Regel nicht brechen.

Es gab tatsächlich genügend Ähnlichkeiten zwischen den beiden, um sie in einem schier endlosen Strom von Blogposts und Think-Pieces gegeneinander auszuspielen. MooTools vs. jQuery, eine Frage der Zeit. Websites entstanden, um die beiden zu vergleichen. MooTools war ein „Framework“, jQuery war eine „Bibliothek“. MooTools machte das Programmieren Spaß, jQuery machte das Web spaßig. MooTools war für Zwillinge und jQuery für Schützen. In Wahrheit funktionierten beide sehr gut, und die Verwendung des einen über das andere war meist eine Frage der persönlichen Vorliebe. Dies gilt weitgehend für viele der gängigsten Debatten über Entwicklerbibliotheken, aber sie gehen trotzdem weiter.

Das Erbe von Legacy-Frameworks

Letztendlich haben nicht Features oder Code-Struktur gewonnen – es war die Zeit. Einer nach dem anderen zogen sich die Kern-Mitwirkenden von MooTools aus dem Projekt zurück, um an anderen Dingen zu arbeiten. Bis 2010 blieben nur noch wenige übrig. Die Entwicklung verlangsamte sich, und die Community folgte kurz darauf. MooTools blieb beliebt, aber seine Dynamik kam zum Stillstand.

Der Vorteil von jQuery war einfach, dass sie weitermachten, sogar expandierten. Im Jahr 2010, als die Entwicklung von MooTools langsam zurückging, veröffentlichte jQuery die erste Version von jQuery Mobile, einen Versuch, die Bibliothek für eine mobile Welt neu zu gestalten. Die jQuery-Community gab nie auf, und am Ende verschaffte ihnen das den Vorteil.

Das Erbe und die Reichweite von MooTools sind jedoch immens. Es fand seinen Weg auf Hunderttausende von Websites und verbreitete sich auf der ganzen Welt. Laut einigen Statistiken ist es auch heute noch auf durchschnittlichen Websites häufiger anzutreffen als Angular, React, Vue oder jedes moderne Framework. Der Code einiger Websites wurde aktualisiert, um mit den weitaus selteneren, aber dennoch gelegentlichen Updates von MooTools Schritt zu halten. Andere sind bis heute mit welcher Version von MooTools auch immer sie installiert haben, zufrieden. Die meisten haben ihre Website einfach überhaupt nicht aktualisiert. Als die Website erstellt wurde, war MooTools die beste verfügbare Option, und jetzt, Jahre später, bleibt dieselbe Version bestehen.

Array.flatten

Was uns ganz zum Bug in der Wetter-App zurückbringt, der Anfang 2018 in Firefox auftauchte. Denken Sie daran, MooTools wurde nach dem Vorbild von Prototype entwickelt. Es modifizierte native JavaScript-Prototypen, um einige Funktionen hinzuzufügen, die geplant, aber noch nicht veröffentlicht waren. In diesem speziellen Fall war es eine Methode namens Array.flatten, eine Funktion, die MooTools 2008 zu seiner Bibliothek hinzufügte, um Arrays zu modifizieren. Spulen wir 10 Jahre vor, und die JavaScript-Arbeitsgruppe nahm sich endlich die Implementierung ihrer eigenen Version von Array.flatten vor, beginnend mit der Beta-Version von Firefox.

Das Problem war, dass die Array.flatten-Implementierung von Firefox nicht direkt mit der MooTools-Version von Array.flatten übereinstimmte.

Die Details sind nicht so wichtig (obwohl Sie hier mehr darüber lesen können). Viel kritischer war die unbequeme Implikation. Die MooTools-Version würde in ihrer jetzigen Form brechen, wenn sie mit der neuen JavaScript-Version kollidierte. Das ist es, was das Wetter-Widget kaputt gemacht hat. Wenn Firefox seinen Browser der breiten Öffentlichkeit zugänglich gemacht hätte, würde die MooTools-Version von flatten einen Fehler auslösen und jegliches JavaScript, das davon abhing, ausradieren. Niemand konnte sagen, wie viele Websites von dem Konflikt betroffen sein könnten, aber angesichts der Popularität von MooTools war es nicht unwahrscheinlich zu glauben, dass der Schaden erheblich sein könnte.

Nachdem der Bug aufgetaucht war, fanden in der JavaScript-Community, viel davon im öffentlichen GitHub-Repository der JavaScript-Arbeitsgruppe, hitzige Diskussionen statt. Bald tauchten einige Lösungen auf. Die erste bestand darin, einfach die neue Version von flatten zu veröffentlichen. Im Grunde, um die alten Websites kaputtgehen zu lassen. Es wurde argumentiert, dass die vorgeschlagene Lösung eine einfache Eleganz besaß, die grundsätzlich auf der Idee beruhte, dass es die Verantwortung von Browsern ist, das Web voranzutreiben. Das Brechen von Websites würde Website-Besitzer zum Upgrade zwingen, und wir könnten uns endlich der alten und veralteten MooTools-Versionen entledigen.

Andere sprangen schnell ein, um darauf hinzuweisen, dass das Web grenzenlos ist und es unmöglich ist zu verfolgen, welche Websites betroffen sein könnten. Eine gute Anzahl dieser Websites wurde wahrscheinlich seit Jahren nicht aktualisiert. Einige könnten aufgegeben worden sein. Andere hätten möglicherweise nicht die Ressourcen für ein Upgrade. Sollten wir diese Websites dem Verfall überlassen? Der sichere, verzeihende Ansatz wäre, die Funktion entweder rückwärtskompatibel oder vollständig mit MooTools kompatibel zu gestalten. Nach der Veröffentlichung würde nichts kaputt gehen, auch wenn die endgültige Implementierung von Array.flatten nicht ideal war.

Irgendwo dazwischen wurde ein letzter Vorschlag gemacht, dass der beste Kurs darin bestehen könnte, die Funktion einfach umzubenennen, das Problem im Wesentlichen zu umgehen und zu vermeiden, dass die beiden Implementierungen miteinander auskommen müssen.

Ein Entwickler schlug vor, stattdessen den Namen Array.smoosh zu verwenden, was schließlich dazu führte, dass der gesamte Vorfall als Smooshgate bezeichnet wurde, was bedauerlich war, weil es eine viel interessantere Debatte über die Seele des Webs übersah. Es deckte eine wesentliche Frage über die Verantwortung von Browserherstellern und Entwicklern auf, eine zugängliche, offene und fehlerverzeihende Erfahrung für jeden einzelnen Nutzer des Webs und jeden einzelnen Erbauer des Webs zu bieten, selbst wenn (vielleicht besonders wenn) die Standards des Webs vollständig ignoriert werden. Vereinfacht ausgedrückt, lautete die Frage: *Sollten wir das Web jemals kaputt machen?*

Um es klar zu sagen: Das Web ist ein allgegenwärtiges und sich schnell entwickelndes Medium, das ursprünglich zum Teilen von Text und Links und wenig anderem entwickelt wurde, aber jetzt von Milliarden von Menschen täglich in allen Facetten ihres Lebens genutzt wird, um wirklich außergewöhnliche Dinge zu tun. Es wird gelegentlich von selbst kaputtgehen. Aber wenn eine Situation auftritt, die in vollem Umfang sichtbar und letztendlich vermeidbar ist, ist es dann der richtige Weg, zu versuchen, das Web voranzutreiben, oder sicherzustellen, dass das Web in seiner aktuellen Form funktioniert, auch wenn die Technologie voranschreitet?

Dies führt nur zu weiteren Fragen. Wer sollte für diese Entscheidungen verantwortlich sein? Sollte jede Bibliothek auf unbestimmte Zeit aktiv gepflegt werden, auch wenn sich Best Practices zu Anti-Mustern entwickeln? Welche Verpflichtung haben wir als Entwickler für Websites, von denen wir wissen, dass sie aufgegeben wurden? Und vor allem, wie können wir den vielen verschiedenen Nutzern des Webs am besten dienen und ihnen gleichzeitig neue programmatische Werkzeuge zur Verfügung stellen? Dies sind dieselben Fragen, zu denen wir immer wieder zurückkehren, und sie stehen im Mittelpunkt von Diskussionen wie Progressive Enhancement, Responsive Design und Barrierefreiheit.

Wohin gehen wir jetzt?

Es ist unmöglich, all diese Fragen einfach zu beantworten. Sie können jedoch durch das ideologische Projekt des Webs selbst gerahmt werden. Das Web wurde entwickelt, um offen zu sein, sowohl technologisch als dezentrales Netzwerk als auch philosophisch als demokratisierendes Medium. Diese Fragen sind knifflig, weil das Web niemandem gehört, aber für alle geschaffen wurde. Die Aufrechterhaltung dieses Geistes erfordert viel Arbeit und bedarf manchmal langsamer, aber immer überlegter Entscheidungen über die Weiterentwicklung von Webtechnologien. Wir sollten vorsichtig sein, die Berge von Legacy-Code und Bibliotheken zu berücksichtigen, die wahrscheinlich während der gesamten Existenz des Webs im Web bleiben werden. Nicht nur, weil sie oft mit den besten Absichten erstellt wurden, sondern weil viele in das Gewebe des Webs eingewebt wurden. Wenn wir einen Faden zu fest ziehen, riskieren wir, das Ganze zu entwirren.

Während die JavaScript-Arbeitsgruppe auf eine Lösung hinarbeitete, tauchten viele dieser Fragen in der einen oder anderen Form auf. Am Ende war die Lösung ein Kompromiss. Array.flatten wurde in Array.flat umbenannt und ist nun in den meisten modernen Browser-Versionen aktiv. Es ist schwer zu sagen, ob dies die absolut beste Entscheidung war, und sicherlich werden wir nicht immer alles richtig machen. Aber wenn wir uns an die grundlegenden Ideale des Webs erinnern – dass es als zugängliches, inklusives und sich ständig veränderndes Medium aufgebaut wurde, und dies als Leitfaden verwenden –, kann uns das bei unseren Entscheidungen helfen. Dies scheint im Kern des Falles von Smooshgate gestanden zu haben.

Eines Tages surfen Sie vielleicht im Web und stoßen auf eine alte Website, die seit Jahren nicht aktualisiert wurde. Oben sehen Sie vielleicht sogar ein Widget, das Ihnen das Wetter anzeigt. Und es wird weiterhin funktionieren, weil JavaScript beschlossen hat, sich zu beugen, anstatt zu brechen.

Mögen Sie es, etwas über Webgeschichte mit Geschichten wie dieser zu lernen? Jay Hoffmann erzählt die vollständige Geschichte des Webs, vom Anfang an, auf The History of the Web. Melden Sie sich für seinen Newsletter an, um auf dem neuesten Stand zu bleiben... des Vergangenen!