Ein praktischer Leitfaden für ES6-Module

ES6-Module

Eine der größten Herausforderungen beim Erstellen einer Web-App besteht darin, wie schnell Sie skalieren und auf die Anforderungen des Marktes reagieren können. Wenn die Nachfrage (Anforderungen) steigt, steigen auch die Fähigkeiten (Funktionen). Es ist daher wichtig, eine solide architektonische Struktur zu haben, damit die App organisch wächst. Wir möchten nicht in Situationen geraten, in denen die App nicht skaliert werden kann, da alle Elemente in der App eng miteinander verflochten sind.

Schreiben Sie Code, der leicht zu löschen und nicht leicht zu erweitern ist.
- Tef, Programmierung ist schrecklich

In diesem Artikel erstellen wir ein einfaches Dashboard mit ES6-Modulen und stellen anschließend Optimierungstechniken vor, mit denen Sie die Ordnerstruktur verbessern und weniger Code schreiben können. Sehen wir uns an, warum ES6-Module wichtig sind und wie Sie sie effektiv anwenden können.

JavaScript hat seit langer Zeit Module. Sie wurden jedoch über Bibliotheken implementiert, die nicht in die Sprache integriert waren. ES6 ist das erste Mal, dass JavaScript Module enthält (Quelle).

TL; DR - Wenn Sie ein praktisches Beispiel sehen möchten, in dem wir ein Dashboard mit ES6-Modulen aus einem architektonischen Entwurfslayout erstellen, fahren Sie mit Abschnitt 4 fort.

Hier ist was wir ansprechen

  1. Warum werden ES6-Module benötigt?
  2. Damals, als Skripte manuell geladen wurden
  3. Funktionsweise von ES6-Modulen (Import oder Export)
  4. Erstellen wir ein Dashboard mit Modulen
  5. Optimierungstechniken für Dashboard-Beispiel
Wenn Sie ein besserer Webentwickler werden, ein eigenes Unternehmen gründen, andere unterrichten oder Ihre Entwicklungsfähigkeiten verbessern möchten, werde ich wöchentlich Tipps und Tricks zu den neuesten Websprachen veröffentlichen.

1. Warum werden ES6-Module benötigt?

Sehen wir uns ein paar Szenarien an, warum Module relevant sind.

Szenario 1 - Rad nicht neu erfinden

Als Entwickler erstellen wir häufig Dinge, die bereits erstellt wurden, ohne es überhaupt zu merken, oder kopieren und fügen sie ein, um Zeit zu sparen. Am Ende summiert es sich und wir haben noch x identische Kopien, die über die gesamte App verteilt sind. Und für jedes Mal, wenn wir etwas ändern müssen, müssen wir dies x-mal tun, je nachdem, wie viele Kopien wir haben.

Beispiel
Stellen Sie sich zum Beispiel eine Autofabrik vor, die versucht, den Motor jedes Mal neu zu erfinden, wenn ein neues Auto produziert wird, oder einen Architekten, der nach jeder Zeichnung von vorne anfängt. Es ist nicht unmöglich, dies zu tun, aber was ist dann der Sinn des Wissens, wenn Sie die gesammelten Erfahrungen nicht wiederverwenden können.

Szenario 2 - Wissensbarriere

Wenn das System stark verwickelt ist und es an Dokumentation mangelt, ist es für alte / neue Entwickler schwierig zu lernen, wie die App funktioniert und wie die Dinge miteinander verbunden sind.

Beispiel
Zum Beispiel sollte ein Entwickler in der Lage sein, das Ergebnis einer Änderung zu sehen, ohne zu raten, da wir sonst viele Fehler bekommen, ohne zu wissen, wo wir anfangen sollen. Eine Lösung ist die Verwendung von Modulen zur Kapselung des Verhaltens. Wir können den Debug-Prozess auf einfache Weise eingrenzen und die Ursache des Problems schnell identifizieren.

Ich habe kürzlich einen Artikel über "Entwickler, die ständig neue Dinge lernen möchten" geschrieben, mit Tipps zur Verbesserung des Wissens.

Szenario 3 - Unerwartetes Verhalten

Durch die Vermeidung von Separation-of-Concerns (Konstruktionsprinzip) kann es zu unerwartetem Verhalten kommen.

Beispiel
Nehmen wir zum Beispiel an, jemand erhöht die Lautstärke im Auto und das startet die Scheibenwischer. Das ist ein Beispiel für ein unerwartetes Verhalten und nicht etwas, das wir in unserer Anwendung wollen.

Kurz gesagt, wir benötigen ES6-Module, um internes Verhalten von externem Verhalten effektiv wiederzuverwenden, zu verwalten, zu trennen und zu kapseln. Es geht nicht darum, das System komplexer zu gestalten, sondern darum, Dinge einfach zu skalieren und zu löschen, ohne das System zu beschädigen.

2. Damals, als Skripte manuell geladen wurden

Wenn Sie einige Jahre lang mit der Webentwicklung gearbeitet haben, sind auf jeden Fall Abhängigkeitskonflikte aufgetreten, z. B. dass Skripts nicht in der richtigen Reihenfolge geladen werden oder dass JS nicht auf die Elemente des DOM-Baums zugreifen kann.

Der Grund dafür ist, dass der HTML-Code auf einer Seite in der angegebenen Reihenfolge geladen wird. Dies bedeutet, dass keine Skripts geladen werden können, bevor der Inhalt im -Element vollständig geladen wurde.

Wenn Sie beispielsweise versuchen, mit document.getElementById ("id-name") auf ein Element im -Tag zuzugreifen und das Element noch nicht geladen ist, wird ein undefinierter Fehler angezeigt. Um sicherzustellen, dass die Skripte richtig geladen werden, können wir defer und async verwenden. Ersteres stellt sicher, dass jedes Skript in der Reihenfolge geladen wird, in der es angezeigt wird, während letzteres das Skript lädt, sobald es verfügbar ist.

Die altmodische Methode zur Lösung dieses Problems bestand darin, die Skripte direkt vor dem -Element zu laden.

Aber auf lange Sicht summiert sich die Anzahl der Skripte und es können mehr als 10 Skripte bei dem Versuch entstehen, Versions- und Abhängigkeitskonflikte beizubehalten.

Trennung von Bedenken

Im Allgemeinen ist das Laden von Skripten wie oben gezeigt in Bezug auf Leistung, Abhängigkeiten und Wartbarkeit keine gute Idee. Wir möchten nicht, dass die Datei index.html die Verantwortung für das Laden aller Skripte trägt - wir benötigen eine Art Struktur und Trennung der Logik.

Die Lösung besteht darin, die Syntax-, Import- und Exportanweisungen von ES6 zu verwenden. Dies ist ein eleganter und wartbarer Ansatz, mit dem wir die Dinge getrennt halten können und der nur dann verfügbar ist, wenn wir ihn benötigen.

Die Import- und Exportanweisungen

Das Schlüsselwort export wird verwendet, wenn irgendwo etwas verfügbar sein soll, und der Import wird verwendet, um auf das zuzugreifen, was der Export verfügbar gemacht hat.

Die Faustregel lautet: Um etwas zu importieren, müssen Sie es zuerst exportieren.

Und was können wir eigentlich exportieren?

  • Eine Variable
  • Ein Objekt-Literal
  • Eine Klasse
  • Eine Funktion
  • ++

Um das oben gezeigte Beispiel zu vereinfachen, können wir alle Skripte in eine Datei packen.

Laden Sie dann einfach das Skript app.js in unsere index.html. Damit dies funktioniert, müssen wir zunächst type = "module" (source) verwenden, damit wir den Import und Export für die Arbeit mit Modulen verwenden können.

Wie Sie sehen, ist die index.html jetzt für ein Skript verantwortlich, was die Pflege und Skalierung erleichtert. Kurz gesagt, das Skript app.js wird zu unserem Einstiegspunkt, über den wir unsere Anwendung booten können.

Hinweis: Ich würde nicht empfehlen, alle Skripte in einer Datei wie app.js zu laden, mit Ausnahme derjenigen, die dies erfordern.

Nachdem wir nun gesehen haben, wie wir die Import- und Exportanweisungen verwenden können, wollen wir uns ansehen, wie es funktioniert, wenn wir in der Praxis mit Modulen arbeiten.

3. Funktionsweise von ES6-Modulen

Was ist der Unterschied zwischen einem Modul und einer Komponente? Ein Modul ist eine Sammlung kleiner unabhängiger Einheiten (Komponenten), die wir in unserer Anwendung wiederverwenden können.

Was ist der Zweck?

  • Verkapseln Sie das Verhalten
  • Leicht damit zu arbeiten
  • Pflegeleicht
  • Einfach zu skalieren

Ja, das erleichtert die Entwicklung!

Was ist eigentlich eine Komponente?

Eine Komponente kann eine Variable, eine Funktion, eine Klasse usw. sein. Mit anderen Worten, alles, was mit der export-Anweisung exportiert werden kann, ist eine Komponente (oder Sie können es einen Block, eine Einheit usw. nennen).

Was ist eine Komponente?

Was ist eigentlich ein Modul?

Wie bereits erwähnt, ist ein Modul eine Sammlung von Komponenten. Wenn wir mehrere Komponenten haben, die kommunizieren oder einfach zusammen gezeigt werden müssen, um ein integriertes Ganzes zu bilden, benötigen Sie höchstwahrscheinlich ein Modul.

Was ist ein Modul?

Es ist eine Herausforderung, alles wiederverwendbar zu machen

Ein Hauptingenieur mit über 30 Jahren Erfahrung in der Elektrotechnik sagte einmal, wir können nicht erwarten, dass alles wiederverwendet wird, weil Zeit, Kosten und nicht alles wiederverwendet werden soll. Es ist besser, Dinge zu einem gewissen Grad wiederzuverwenden, als eine 100% ige Wiederverwendung zu erwarten.

Im Allgemeinen bedeutet dies, dass wir nicht alles in der App wiederverwendbar machen müssen. Einige Dinge sollen nur einmal verwendet werden. Als Faustregel gilt: Wenn Sie mehr als zwei Mal etwas benötigen, ist es möglicherweise eine gute Idee, ein Modul oder eine Komponente zu erstellen.

Zunächst mag es einfach klingen, etwas wiederverwendbar zu machen, aber denken Sie daran, dass Sie die Komponente aus ihrer Umgebung entfernen müssen, und erwarten, dass sie in einer anderen funktioniert. Aber oft müssen wir Teile davon modifizieren, um es wieder voll verwendbar zu machen, und bevor Sie es wissen, haben Sie zwei neue Komponenten erstellt.

Antoine hat einen Artikel geschrieben, in dem drei grundlegende Regeln für die Erstellung wiederverwendbarer JS-Komponenten beschrieben sind. Lesen Sie diesen Artikel. Als er seinem Team VueJS vorstellte, sagte ein erfahrener Mitarbeiter:

Das ist in der Theorie großartig, aber meiner Erfahrung nach werden diese ausgefallenen "wiederverwendbaren" Dinge nie wiederverwendet.

Die Idee ist, dass nicht alles, wie Schaltflächen, Eingabefelder und Kontrollkästchen, wiederverwendet werden sollte. Die gesamte Arbeit, um etwas wiederverwendbar zu machen, erfordert Ressourcen und Zeit, und oftmals kommt es zu überlegten Szenarien, die niemals auftreten würden.

Der CEO von Stack Overflow, Joel Spolsky, sagt:

Eine zu 50% gute Lösung, die die Leute tatsächlich haben, löst mehr Probleme und überlebt länger als eine zu 99% Lösung, die niemand hat, weil Sie in Ihrem Labor das verdammte Ding endlos polieren. Der Versand ist ein Feature. Ein wirklich wichtiges Feature. Ihr Produkt muss es haben.

4. Erstellen wir ein Dashboard mit Modulen

Nachdem wir nun ein grundlegendes Verständnis für die Funktionsweise von Modulen haben, sehen wir uns ein praktisches Beispiel an, auf das Sie wahrscheinlich beim Arbeiten mit JS-Frameworks stoßen werden. Wir erstellen ein einfaches Dashboard nach einem Architekturentwurf, der aus Layouts und Komponenten besteht.

Den Code für das Beispiel finden Sie hier.

Schritt 1 - Entwerfen Sie, was Sie brauchen

In den meisten Fällen sprangen Entwickler direkt in den Code. Design ist jedoch ein wichtiger Bestandteil der Programmierung und kann Ihnen viel Zeit und Kopfschmerzen ersparen. Denken Sie daran, Design sollte nicht perfekt sein, sondern etwas, das Sie in die richtige Richtung führt.

Das ist es, was wir basierend auf dem architektonischen Entwurf brauchen.

  • Komponenten: users.js, user-profile.js und issues.js
  • Layouts: header.js und sidebar.js
  • Dashboard: dashboard.js

Alle Komponenten und Layouts werden in dashboard.js geladen und anschließend werden dashboard.js in index.js gebootet.

Architektonische Gestaltung unseres Armaturenbretts

Warum haben wir also einen Ordner für Layouts und Komponenten?

Ein Layout ist etwas, das wir einmal brauchen, zum Beispiel eine statische Vorlage. Der Inhalt im Dashboard kann sich ändern, die Seitenleiste und die Kopfzeile bleiben jedoch unverändert (und dies sind sogenannte Layouts). Ein Layout kann entweder eine Fehlerseite, eine Fußzeile, eine Statusseite usw. sein.

Der Komponentenordner ist für allgemeine Komponenten gedacht, die wir höchstwahrscheinlich mehrmals verwenden werden.

Beim Umgang mit Modulen ist es wichtig, eine solide Bodenstruktur zu haben. Um effektiv skalieren zu können, müssen Ordner über angemessene Namen verfügen, die das Auffinden und Debuggen von Inhalten vereinfachen.

Später zeige ich Ihnen, wie Sie eine dynamische Benutzeroberfläche erstellen, für die ein Ordnerplatz für die benötigten Komponenten und Layouts erforderlich ist.

Schritt 2 - Ordnerstruktur einrichten

Wie bereits erwähnt, haben wir 3 Hauptordner: Dashboard, Komponenten und Layouts.

- Instrumententafel
- Komponenten
- Layouts
index.html
index.js (Einstiegspunkt)

Und in jede Datei innerhalb des Ordners exportieren wir eine Klasse.

- Instrumententafel
    dashboard.js
- Komponenten
    issues.js
    user-profile.js
    users.js
- Layouts
    header.js
    sidebar.js
index.html
index.js (Einstiegspunkt)

Schritt 3 - Implementierung

Die Ordnerstruktur ist festgelegt. Als Nächstes müssen Sie die Komponente (eine Klasse) in jeder Datei erstellen und anschließend exportieren. Die Codekonvention ist für den Rest der Dateien dieselbe: Jede Komponente ist einfach eine Klasse und eine Methode, die „x component is loaded“ (x ist der Name der Komponente) konsolidiert, um anzuzeigen, dass die Komponente geladen wurde.

Erstellen Sie eine Benutzerklasse und exportieren Sie sie wie unten gezeigt.

Beachten Sie, dass wir beim Umgang mit der Exportanweisung verschiedene Optionen haben. Die Idee ist also, dass Sie entweder einzelne Komponenten oder eine Sammlung von Komponenten exportieren können. Wenn wir beispielsweise die Klasse exportieren, können wir auf die darin deklarierten Methoden zugreifen, indem wir eine neue Instanz der Klasse erstellen.

Okay, wenn Sie sich das Architekturdiagramm in Schritt 1 ansehen, werden Sie feststellen, dass die Benutzerprofilkomponente vom Header-Layout eingekapselt wird. Dies bedeutet, dass beim Laden des Header-Layouts auch die Benutzerprofilkomponente geladen wird.

Nachdem jede Komponente und jedes Layout eine exportierte Klasse hat, importieren wir sie wie folgt in unsere Dashboard-Datei:

Um zu verstehen, was in der Dashboard-Datei wirklich vor sich geht, müssen Sie die Zeichnung in Schritt 1 erneut aufrufen. Da es sich bei jeder Komponente um eine Klasse handelt, müssen Sie eine neue Instanz erstellen und sie dann einem Objekt zuweisen. Dann verwenden wir das Objekt, um die Methoden wie in der Methode loadDashboard () gezeigt auszuführen.

Derzeit gibt die App nichts aus, da wir die Methode loadDashboard () nicht ausgeführt haben. Damit es funktioniert, müssen wir das Dashboard-Modul in die Datei index.js wie folgt importieren:

Und dann gibt die Konsole Folgendes aus:

ES6-Komponenten geladen

Wie gezeigt funktioniert alles und die Komponenten werden erfolgreich geladen. Wir können auch zwei Instanzen erstellen und dann so etwas tun:

Was dasselbe ausgibt wie oben, aber da wir neue Instanzen haben, erhalten wir die Ergebnisse zweimal.

Zwei einzigartige Dashboard-Instanzen

Im Allgemeinen können wir so das Modul in den benötigten Dateien einfach warten und wiederverwenden, ohne andere Module zu beeinträchtigen. Wir erstellen gerade eine neue Instanz, die die Komponenten kapselt.

Wie bereits erwähnt, sollte die Dynamik der Arbeit mit Modulen und Komponenten mithilfe der Import- und Exportanweisungen abgedeckt werden.

In den meisten Fällen verfügen wir bei der Arbeit mit JS-Frameworks über eine Route, die den Inhalt des Dashboards ändern kann. Derzeit wird jedes Mal, wenn wir die Methode loadDashboard () aufrufen, alles geladen, z. B. Layouts. Dies ist kein idealer Ansatz.

5. Optimierungstechniken für Dashboard-Beispiel

Da wir nun ein grundlegendes Verständnis der Funktionsweise von Modulen haben, ist der Ansatz bei großen Anwendungen, die aus vielen Komponenten bestehen, nicht wirklich skalierbar oder intuitiv.

Wir brauchen etwas, das als dynamische Schnittstelle bekannt ist. Auf diese Weise können wir eine Sammlung der benötigten Komponenten erstellen und problemlos darauf zugreifen. Wenn Sie Visual Studio Code verwenden, zeigt Ihnen IntelliSense, welche Komponenten verfügbar sind und welche Sie bereits verwendet haben. Es bedeutet, dass Sie den Ordner / die Datei nicht manuell öffnen müssen, um zu sehen, welche Komponenten exportiert wurden.

Wenn wir also ein Modul mit zwanzig Komponenten haben, möchten wir nicht jede Komponente zeilenweise nacheinander importieren. Wir wollen einfach nur das bekommen, was wir brauchen, und das war's. Wenn Sie mit Namespaces in Sprachen wie C #, PHP, C ++ oder Java gearbeitet haben, werden Sie feststellen, dass dieses Konzept ähnlicher Natur ist.

Folgendes möchten wir erreichen:

Wie gezeigt, haben wir weniger Codezeilen und haben sie deklarativ gemacht, ohne den Kontext zu verlieren. Mal sehen, welche Änderungen wir vorgenommen haben.

Erstellen Sie eine dynamische Schnittstelle (auch als Fässer bezeichnet)

Über eine dynamische Oberfläche können wir eine Sammlung von Dingen erstellen, die wir benötigen. Es ist wie beim Erstellen einer Toolbox mit unseren Lieblingswerkzeugen. Zu erwähnen ist, dass nicht in jedem einzelnen Ordner eine dynamische Schnittstelle hinzugefügt werden sollte, sondern in Ordnern, die aus vielen Komponenten bestehen.

Sie vereinfachen den Import erheblich und machen ihn übersichtlicher. Wir möchten nur nicht zu viele Barrel-Dateien haben, da dies kontraproduktiv ist und normalerweise zu Problemen mit zirkulären Abhängigkeiten führt, deren Lösung manchmal recht schwierig sein kann.
- Adrian Fâciu

Um eine dynamische Schnittstelle zu erstellen, erstellen wir eine Datei mit dem Namen index.js, die sich im Stammverzeichnis jedes Ordners befindet, um eine Teilmenge der benötigten Dateien oder Komponenten erneut zu exportieren. Dasselbe Konzept funktioniert in TypeScript. Sie ändern lediglich den Typ von .js in .ts wie in index.ts.

Index.js ist die erste Datei, die geladen wird, wenn wir auf den Stammordnerbereich zugreifen. Es ist dasselbe Konzept wie index.html, das unseren HTML-Inhalt startet. Dies bedeutet, dass wir nicht explizit den Import {component} von './components/index.js' schreiben müssen, sondern stattdessen den Import {component} von './components.

So sieht eine dynamische Benutzeroberfläche aus.

Durch die Verwendung einer dynamischen Schnittstelle haben wir eine Root-Ebene weniger Zugriff und auch weniger Code.

Erstellen Sie zur Laufzeit eine neue Instanz

Wir haben die vier Instanzen in unserer dashboard.js entfernt und stattdessen zur Laufzeit eine Instanz erstellt, wenn jede Komponente exportiert wird. Wenn Sie den Namen des Objekts festlegen möchten, können Sie das neue Standard-Dashboard () exportieren und anschließend dashView ohne geschweifte Klammern importieren.

Wie gezeigt, können wir die Methode direkt aufrufen, ohne eine neue Instanz erstellen zu müssen, und auch weniger Code schreiben. Dies ist jedoch eine persönliche Präferenz und Sie können frei entscheiden, was ein praktischer Anwendungsfall für Ihre App und Ihre Anforderungen ist.

Und schließlich laden wir alle Komponenten und Layouts mit einer Methode.

Fazit

Ich wollte zunächst nur ein kurzes Beispiel zeigen, wie Sie eine Komponente importieren und exportieren können, musste dann aber (fast) alles teilen, was ich weiß. Ich hoffe, dieser Artikel bietet Ihnen einen Einblick in den effektiven Umgang mit ES6-Modulen beim Erstellen von Apps sowie in die Aspekte, die für die Trennung von Anliegen wichtig sind (Entwurfsprinzip).

Die Imbissbuden:

  • Mit ES6-Modulen können wir Komponenten problemlos wiederverwenden, warten, trennen und kapseln, damit sie nicht durch externes Verhalten verändert werden
  • Ein Modul ist eine Sammlung von Komponenten
  • Eine Komponente ist ein einzelner Block
  • Versuchen Sie nicht, alles wiederverwendbar zu machen, da dies Zeit und Ressourcen erfordert. In den meisten Fällen wird es nicht wiederverwendet
  • Erstellen Sie ein Architekturdiagramm, bevor Sie in den Code eintauchen
  • Um Komponenten in anderen Dateien verfügbar zu machen, müssen wir zuerst exportieren und dann importieren
  • Mithilfe von index.js (dasselbe Konzept wie für TypeScript index.ts) können wir dynamische Schnittstellen (Barrels) erstellen, um mit weniger Code und weniger hierarchischen Pfaden schnell auf die benötigten Elemente zuzugreifen
  • Sie können eine neue Instanz zur Laufzeit exportieren, indem Sie export let objectName = new ClassName () verwenden.

Die gute Nachricht ist, dass sich die Dinge geändert haben und wir uns einem komponentenbasierten und wiederverwendbaren Paradigma nähern. Die Frage ist, wie wir nicht nur einfachen JS-Code, sondern auch HTML-Elemente auf praktische und intuitive Weise wiederverwenden können. Es sieht so aus, als würden uns ES6-Module in Kombination mit Webkomponenten nur das liefern, was wir zum Erstellen von performanten und skalierbaren Apps benötigen.

Hier sind ein paar Artikel, die ich über das Web-Ökosystem geschrieben habe, sowie Tipps und Tricks zur persönlichen Programmierung.

  • Ein Vergleich zwischen Angular und React
  • Ein chaotischer Verstand führt zu chaotischem Code
  • Entwickler, die ständig neue Dinge lernen wollen
  • Lernen Sie diese grundlegenden Webkonzepte kennen
  • Steigern Sie Ihre Fähigkeiten mit diesen wichtigen JavaScript-Methoden
  • Programmieren Sie schneller, indem Sie benutzerdefinierte Bash-Befehle erstellen

Sie finden mich auf Medium, wo ich wöchentlich veröffentliche. Oder folgen Sie mir auf Twitter, wo ich relevante Tipps und Tricks zur Webentwicklung zusammen mit persönlichen Entwicklergeschichten veröffentliche.

Wenn dir dieser Artikel gefallen hat und du mehr davon haben möchtest, klatsche (❤) und teile ihn mit Freunden oder Kollegen. Das ist gutes Karma.