7 days of WordPress plugins, themes & templates - for free!* Unlimited asset downloads! Start 7-Day Free Trial
Advertisement
  1. Code
  2. JavaScript

Module, ein zukünftiger Ansatz für JavaScript-Bibliotheken

Scroll to top
Read Time: 15 mins

German (Deutsch) translation by Federicco Ancie (you can also view the original English article)

JavaScript-Bibliotheken wie jQuery sind seit fast einem Jahrzehnt die erste Wahl, um JavaScript im Browser zu schreiben. Sie waren ein großer Erfolg und eine notwendige Intervention für das Land eines Browsers voller Diskrepanzen und Implementierungsprobleme. jQuery beschönigte nahtlos Browser-Fehler und Macken und machte es zu einem Kinderspiel, Dinge wie Ereignisbehandlung, Ajax- und DOM-Manipulation zu erledigen.

Zu dieser Zeit hat jQuery alle unsere Probleme gelöst, wir schließen seine allmächtige Kraft ein und machen uns sofort an die Arbeit. In gewisser Weise war es eine Black Box, die der Browser „brauchte“, um richtig zu funktionieren.

Aber das Web hat sich weiterentwickelt, APIs verbessern sich, Standards werden implementiert, das Web ist eine sehr schnelllebige Szene und ich bin nicht sicher, ob riesige Bibliotheken in Zukunft einen Platz für den Browser haben. Es wird eine modulorientierte Umgebung.

Betreten Sie das Modul

Ein Modul ist eine gekapselte Funktionalität, die nur eines und das eine sehr gut kann. Beispielsweise kann ein Modul dafür verantwortlich sein, einem Element Klassen hinzuzufügen, über HTTP über Ajax zu kommunizieren usw. - es gibt endlose Möglichkeiten.

Ein Modul kann in vielen Formen und Größen erhältlich sein. Der allgemeine Zweck besteht jedoch darin, in eine Umgebung importiert zu werden und sofort einsatzbereit zu sein. Im Allgemeinen verfügt jedes Modul über grundlegende Dokumentations- und Installationsprozesse für Entwickler sowie über die Umgebungen, für die es bestimmt ist (z. B. Browser, Server).

Diese Module werden dann zu Projektabhängigkeiten, und die Abhängigkeiten werden einfach zu verwalten. Die Tage, in denen Sie in einer riesigen Bibliothek vorbeischauen, vergehen langsam. Große Bibliotheken bieten nicht so viel Flexibilität oder Leistung. Bibliotheken wie jQuery haben dies ebenfalls erkannt, was fantastisch ist. Sie sind ein Online-Tool, mit dem Sie nur die benötigten Dinge herunterladen können.

Moderne APIs sind ein großer Anreiz für die Inspiration von Modulen. Nachdem sich die Browser-Implementierungen drastisch verbessert haben, können wir kleine Dienstprogrammmodule erstellen, die uns bei der Erfüllung unserer häufigsten Aufgaben helfen.

Die Modul-Ära ist da und sie ist da, um zu bleiben.

Inspiration für ein erstes Modul

Eine moderne API, an der ich seit ihrer Einführung immer interessiert war, ist die classList-API. Inspiriert von Bibliotheken wie jQuery haben wir jetzt eine native Möglichkeit, einem Element Klassen ohne Bibliothek oder Dienstprogrammfunktionen hinzuzufügen.

Die classList-API gibt es schon seit einigen Jahren, aber nicht viele Entwickler wissen davon. Dies hat mich dazu inspiriert, ein Modul zu erstellen, das die classList-API verwendet, und für diejenigen Browser, die weniger Glück haben, diese zu unterstützen, eine Art Fallback-Implementierung bereitzustellen.

Bevor wir uns mit dem Code befassen, schauen wir uns an, was jQuery in die Szene gebracht hat, um einem Element eine Klasse hinzuzufügen:

Als diese Manipulation nativ landete, endeten wir mit der oben genannten classList-API - einem DOMTokenList-Objekt (durch Leerzeichen getrennte Werte), das die Werte darstellt, die für den className eines Elements gespeichert sind. Die classList-API bietet uns einige Methoden zur Interaktion mit dieser DOMTokenList, die alle sehr "jQuery-ähnlich" sind. Hier ist ein Beispiel dafür, wie die classList-API eine Klasse hinzufügt, die die classList.add() Methode verwendet:

Was können wir daraus lernen? Eine Bibliotheksfunktion, die ihren Weg in eine Sprache findet, ist eine ziemlich große Sache (oder inspiriert sie zumindest). Das ist es, was an der offenen Webplattform so großartig ist, dass wir alle einen Einblick in den Fortschritt der Dinge haben können.

Also, was kommt als nächstes? Wir kennen uns mit Modulen aus und mögen die classList-API, aber leider unterstützen sie noch nicht alle Browser. Wir könnten jedoch einen Fallback schreiben. Klingt nach einer guten Idee für ein Modul, das bei Unterstützung classList verwendet, oder wenn nicht, automatische Fallbacks.

Erstellen eines ersten Moduls: Apollo.js

Vor ungefähr sechs Monaten habe ich ein eigenständiges und sehr leichtes Modul zum Hinzufügen von Klassen zu einem Element in einfachem JavaScript erstellt - am Ende habe ich es apollo.js genannt.

Das Hauptziel des Moduls bestand darin, die brillante classList-API zu verwenden und keine Bibliothek mehr für eine sehr einfache und allgemeine Aufgabe zu benötigen. jQuery verwendete die classList-API nicht (und verwendet sie immer noch nicht), daher dachte ich, dass dies eine großartige Möglichkeit wäre, mit der neuen Technologie zu experimentieren.

Wir werden durchgehen, wie ich es auch gemacht habe und welche Gedanken hinter jedem Stück stecken, aus dem das einfache Modul besteht.

Verwenden von classList

Wie wir bereits gesehen haben, ist classList eine sehr elegante API und "jQuery-Entwicklerfreundlich". Eine Sache, die mir nicht gefällt, ist die Tatsache, dass wir immer wieder auf das classList-Objekt verweisen müssen, um eine seiner Methoden zu verwenden. Ich wollte diese Wiederholung entfernen, als ich Apollo schrieb und mich für das folgende API-Design entschied:

Ein gutes Klassenmanipulationsmodul sollte die Methoden hasClass, addClass, removeClass und toggleClass enthalten. Alle diese Methoden werden aus dem "Apollo" -Namensraum entfernt.

Wenn Sie sich die obige Methode "addClass" genauer ansehen, sehen Sie, dass ich das Element als erstes Argument übergebe. Im Gegensatz zu jQuery, einem riesigen benutzerdefinierten Objekt, an das Sie gebunden sind, akzeptiert dieses Modul ein DOM-Element. Wie es diesem Element zugeführt wird, hängt vom Entwickler, den nativen Methoden oder einem Auswahlmodul ab. Das zweite Argument ist ein einfacher String-Wert, ein beliebiger Klassenname.

Lassen Sie uns die restlichen Methoden zur Klassenmanipulation durchgehen, die ich erstellen wollte, um zu sehen, wie sie aussehen:

Wo fangen wir an? Erstens benötigen wir ein Objekt, zu dem wir unsere Methoden hinzufügen können, und einen Funktionsabschluss, um alle internen Funktionen/Variablen/Methoden aufzunehmen. Mit einem sofort aufgerufenen Funktionsausdruck (IIFE) verpacke ich ein Objekt namens apollo (und einige Methoden, die classList-Abstraktionen enthalten), um unsere Moduldefinition zu erstellen.

Jetzt, da classList funktioniert, können wir über die Unterstützung älterer Browser nachdenken. Das Ziel des apollomodule ist es, eine winzige und eigenständige konsistente API-Implementierung für die Klassenmanipulation bereitzustellen, unabhängig vom Browser. Hier kommt die einfache Funktionserkennung ins Spiel.

Der einfache Weg, um das Vorhandensein von Features für classList zu testen, ist folgender:

Wir verwenden den Operator in, der das Vorhandensein von classList in Boolean auswertet. Der nächste Schritt wäre die bedingte Bereitstellung der API für classList, die nur Benutzer unterstützt:

Legacy-Unterstützung kann auf verschiedene Arten erfolgen: Lesen Sie die className-Zeichenfolge und durchlaufen Sie alle Namen, ersetzen Sie sie, fügen Sie sie hinzu usw. jQuery verwendet hierfür viel Code, verwendet lange Schleifen und eine komplexe Struktur. Ich möchte dieses frische und leichte Modul nicht vollständig aufblähen. Verwenden Sie daher einen regulären Ausdruck, der ersetzt und ersetzt, um genau den gleichen Effekt mit next zu erzielen zu überhaupt keinem Code.

Hier ist die sauberste Implementierung, die ich finden konnte:

Integrieren wir sie in das Modul und fügen den else-Teil für nicht unterstützende Browser hinzu:

Eine funktionierende jsFiddle von dem, was wir bisher gemacht haben.

Lassen wir es dort, das Konzept wurde geliefert. Das Apollo-Modul verfügt über einige weitere Funktionen, z. B. das gleichzeitige Hinzufügen mehrerer Klassen. Bei Interesse können Sie dies hier überprüfen.

Also, was haben wir getan? Erstellt eine gekapselte Funktionalität, die sich einer Sache und einer Sache gut widmet. Das Modul ist sehr einfach zu lesen und zu verstehen, und Änderungen können neben Unit-Tests leicht vorgenommen und validiert werden. Wir haben auch die Möglichkeit, Apollo für Projekte zu verwenden, bei denen wir jQuery und sein riesiges Angebot nicht benötigen, und das winzige Apollo-Modul wird ausreichen.

Abhängigkeitsmanagement: AMD und CommonJS

Das Konzept der Module ist nicht neu, wir verwenden sie ständig. Sie wissen wahrscheinlich, dass es bei JavaScript nicht mehr nur um den Browser geht, sondern auf Servern und sogar Fernsehgeräten.

Welche Muster können wir beim Erstellen und Verwenden dieser neuen Module anwenden? Und wo können wir sie verwenden? Es gibt zwei Konzepte namens "AMD" und "CommonJS". Lassen Sie uns diese unten untersuchen.

AMD

Die asynchrone Moduldefinition (normalerweise als AMD bezeichnet) ist eine JavaScript-API zum Definieren von Modulen, die asynchron geladen werden sollen. Diese werden normalerweise im Browser ausgeführt, da beim synchronen Laden Leistungskosten sowie Probleme mit Benutzerfreundlichkeit, Debugging und domänenübergreifendem Zugriff entstehen. AMD kann die Entwicklung unterstützen und JavaScript-Module in vielen verschiedenen Dateien kapseln.

AMD verwendet eine Funktion namens define, die ein Modul selbst und alle Exportobjekte definiert. Mit AMD können wir auch auf Abhängigkeiten verweisen, um andere Module zu importieren. Ein kurzes Beispiel aus dem AMD GitHub-Projekt:

Wir könnten so etwas für Apollo tun, wenn wir einen AMD-Ansatz verwenden würden:

CommonJS

Node.js hat in den letzten Jahren zugenommen, ebenso wie Tools und Muster für das Abhängigkeitsmanagement. Node.js verwendet CommonJS, das ein Exportobjekt verwendet, um den Inhalt eines Moduls zu definieren. Eine wirklich grundlegende CommonJS-Implementierung könnte folgendermaßen aussehen (die Idee, etwas zu „exportieren“, das an anderer Stelle verwendet werden soll):

Der obige Code würde sich in einer eigenen Datei befinden. Ich habe diesen als someModule.js bezeichnet. Um es an eine andere Stelle zu importieren und verwenden zu können, gibt CommonJS an, dass wir eine Funktion namens "require" verwenden müssen, um einzelne Abhängigkeiten abzurufen:

Wenn Sie auch Grunt/Gulp verwendet haben, sind Sie es gewohnt, dieses Muster zu sehen.

Um dieses Muster mit Apollo zu verwenden, gehen wir wie folgt vor und verweisen auf das export objekt anstelle des Fensters (siehe letzte Zeile exports.apollo = apollo):

Universal Module Definition (UMD)

AMD und CommonJS sind fantastische Ansätze, aber was wäre, wenn wir ein Modul erstellen würden, das in allen Umgebungen funktionieren soll: AMD, CommonJS und der Browser?

Zunächst haben wir einige if- und else Tricks unternommen, um eine Funktion an jeden Definitionstyp zu übergeben, basierend auf den verfügbaren Informationen. Wir haben nach AMD- oder CommonJS-Unterstützung gesucht und sie verwendet, wenn sie vorhanden war. Diese Idee wurde dann angepasst und eine universelle Lösung namens „UMD“ begann. Es packt diesen if/else-Trick für uns und wir übergeben nur eine einzelne Funktion als Referenz auf einen der unterstützten Modultypen. Hier ein Beispiel aus dem Repository des Projekts:

Whoa! Hier passiert viel. Wir übergeben eine Funktion als zweites Argument an den IIFE-Block, der unter einer lokalen Variablennamen factory dynamisch als AMD oder global dem Browser zugewiesen wird. Ja, dies unterstützt CommonJS nicht. Wir können diese Unterstützung jedoch hinzufügen (Kommentare auch dieses Mal entfernen):

Die magische Linie hier ist module.exports = factory, die unsere Factory CommonJS zuweist.

Lassen Sie uns Apollo in dieses UMD-Setup einbinden, damit es in CommonJS-Umgebungen, AMD und im Browser verwendet werden kann! Ich werde das vollständige Apollo-Skript aus der neuesten Version auf GitHub einbinden, damit die Dinge etwas komplexer aussehen als oben beschrieben (einige neue Funktionen wurden hinzugefügt, aber in den obigen Beispielen nicht absichtlich enthalten):

Wir haben unser Modul so erstellt, dass es in vielen Umgebungen funktioniert. Dies gibt uns enorme Flexibilität, wenn wir neue Abhängigkeiten in unsere Arbeit einbringen - etwas, das uns eine JavaScript-Bibliothek nicht bieten kann, ohne es zunächst in kleine funktionale Teile zu zerlegen.

Testen

In der Regel werden unsere Module von Komponententests begleitet, kleinen Bissgrößen-Tests, die es anderen Entwicklern erleichtern, sich Ihrem Projekt anzuschließen und Pull-Anfragen für Funktionserweiterungen einzureichen. Dies ist viel weniger entmutigend als eine große Bibliothek und das Ausarbeiten ihres Build-Systems! Kleine Module werden häufig schnell aktualisiert, während größere Bibliotheken Zeit benötigen, um neue Funktionen zu implementieren und Fehler zu beheben.

Einpacken

Es war großartig, ein eigenes Modul zu erstellen und zu wissen, dass wir viele Entwickler in vielen Entwicklungsumgebungen unterstützen. Dies macht die Entwicklung wartbarer, macht Spaß und wir verstehen die Tools, die wir verwenden, viel besser. Die Module werden von einer Dokumentation begleitet, mit der wir uns relativ schnell vertraut machen und in unsere Arbeit integrieren können. Wenn ein Modul nicht passt, können wir entweder ein anderes finden oder ein eigenes schreiben - etwas, das wir mit einer großen Bibliothek nicht so einfach machen können wie mit einer einzelnen Abhängigkeit, wir möchten uns nicht an eine einzige Lösung binden.

Bonus: ES6-Module

War es nicht toll zu sehen, wie JavaScript-Bibliotheken Muttersprachen durch Dinge wie Klassenmanipulation beeinflusst haben? A Nun, mit ES6 (der nächsten Generation der JavaScript-Sprache) haben wir Gold geschlagen! Wir haben einheimische Importe und Exporte!

Probieren Sie es aus und exportieren Sie ein Modul:

Und importieren:

Weitere Informationen zu ES6 und den Modulspezifikationen finden Sie hier.

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.