Ratgeber

ES-Modules: Für ein schnelleres JavaScript?

(Foto: MeskPhotography/Shutterstock)

ES Modules sind ein offizielles, standardisiertes Modulsystem für JavaScript. Aber was genau bedeutet das eigentlich, welche Probleme löst es und wie funktionieren ES Modules?

Modulsysteme sind nützlich. Sie bieten einen Weg, Code über verschiedene Anwendungen und Plattformen hinweg wiederzuverwenden. Über Im- und Exporte können sie beliebig in anderen Modulen verwendet werden. Sie sind modular, lassen sich unabhängig voneinander editieren und löschen, ohne dass damit die ganze Anwendung crasht.

Nix mehr verpassen: Die t3n Newsletter zu deinen Lieblingsthemen! Jetzt anmelden

ES Modules sind nicht der erste Anlauf, eine Modulfunktionalität zu JavaScript hinzuzufügen. CommonJS, ein Modulsystem für Node.js, gibt es schon seit Jahren. Es wurde entwickelt, um eben diese Lücke zu schließen. CommonJS ermöglicht genau diese Modularität. Nützliche Module können damit zu Packages zusammengefasst und über npm publiziert werden, sehr bekannte Beispiele für solche Packages sind zum Beispiel React, Lodash oder jQuery.

Für Browser gab es bis ECMAScript 6 kein Modulsystem. Mit ECMAScript 6 wurden ES Modules zur JS-Spezifikation hinzugefügt. Mittlerweile wird das Format von allen großen Browsern – Safari, Chrome, Edge und Firefox – unterstützt. Auch Node unterstützt ES Modules seit einiger Zeit.

Der Vorteil dabei: Mit ES Modules können JS-Module theoretisch so indiziert und gecached werden, dass von überall auf sie zugegriffen werden kann. Der Nutzwert ist offenkundig: Durch die Modularisierung wird theoretisch möglich, dass der Browser bei auftretenden Änderungen nur die betroffenen Dateien fetchen muss. Warum das relevant ist? Bis zu 90 Prozent des Codes einer Website stammen aus Open-Source-Packages (React, Lodash, jQuery), die bei jeder Änderung des Source-Codes erneut vom Browser geladen werden müssen.

Was steckt dahinter?

Wer in JavaScript programmiert, jongliert viel mit Variablen. Es geht eigentlich einen Großteil der Zeit darum, Variablen Werte zuzuweisen, Zahlen hinzuzufügen oder Variablen zu kombinieren und sie in einer weiteren zu speichern. Weil das einen so großen Anteil an der Arbeit mit JavaScript ausmacht, hat die Art, wie ihr diese Variablen innerhalb einer Codebase organisiert, einen nicht unerheblichen Einfluss darauf, wie gut ihr euch darin zurechtfindet, wie gut ihr coden könnt und wie einfach oder auch weniger einfach ihr euren Code warten könnt.

Scope in JavaScript

Sich jeweils nur über ein paar wenige Variablen Gedanken machen zu müssen, ist hilfreich. In JavaScript wird das über ein Konzept namens Scope erreicht. Es verhindert, dass Funktionen auf Variablen zugreifen können, die in anderen Funktionen definiert wurden. An sich ist das eine gute Sache. Wenn ihr an einer Funktion arbeitet, müsst ihr nicht darüber nachdenken, was außerhalb des Scope passiert. Der offensichtliche Nachteil: von außerhalb des Scopes, in dem eine Variable definiert ist, auf sie zuzugreifen, geht nicht. Wer das machen will, muss diese Variable in einem höheren Scope definieren, zum Beispiel als globale Variable.

Illustrieren lässt sich das ganz gut mit jQuery: Um jQuery-Plugins zu laden, mussten Entwickler sicherstellen, dass jQuery im globalen Scope war. jQuery global zu definieren, funktioniert, aber daraus ergaben sich andere Schwierigkeiten: Ihr müsst aufpassen, dass alle Script-Tags in der richtigen Reihenfolge sind – und dass niemand diese Reihenfolge durcheinanderbringt. Wenn eine Funktion jQuery nicht dort findet, wo sie erwartet, es zu finden – im globalen Scope –, wird eure Anwendung nicht weiter ausgeführt und ihr bekommt eine Fehlermeldung.

Dieses Verhalten macht es schwierig, eine Codebase zu maintainen. Code zu löschen oder Script-Tags zu entfernen, wird zum Spießrutenlauf. Ihr wisst nie, was ihr mit solchen Änderungen vielleicht kaputt macht. Das ist so, weil die Abhängigkeiten zwischen eurem Code implizit – also nicht klar ersichtlich irgendwo ausformuliert – sind. Jede Funktion kann schließlich auf alle globalen Variablen zugreifen. Deshalb weiß man nie genau, welche Funktionen wovon abhängig sind. Grundsätzlich kann Code im globalen Scope Variablen, die ebenfalls global definiert sind, verändern. Das ist nicht immer gut. Globale Variablen bieten Angriffspunkte für bösartigen Code und generell mehr Möglichkeiten für die Entstehung von Bugs.

Module und der Module-Scope

Über Module könnt ihr diese global definierten Variablen und Funktionen zu Module-Scopes gruppieren. Der Module-Scope erlaubt es, Variablen unter den Funktionen, die sich in einem gemeinsamen Module-Scope befinden, gemeinsam zu verwenden. Die Variablen innerhalb eines Module-Scopes könnt ihr – anders als die innerhalb einer Funktion – auch für andere Module verfügbar machen. In einem Module-Scope kann explizit festgelegt werden, auf welche der darin befindlichen Variablen, Klassen oder Funktionen von außerhalb zugegriffen werden darf.

Den Vorgang des Verfügbarmachens nennt man einen Export. Ein solcher Export ermöglicht es anderen Modulen, explizit zu machen, dass sie von einer Variable, Klasse oder Funktion abhängig sind. Durch diese explizite Abhängigkeit wisst ihr dann genau, welche Module ihr kaputt macht, wenn ihr Variablen, Klassen oder Funktionen verändert oder wegnehmt. So wird es einfacher, Code in kleinere Teile zu splitten, die auch unabhängig von einander funktionieren. Und die sich dann beliebig zu unterschiedlichen Applikationen kombinieren lassen.

Und so funktionieren die Module

Verwendet ihr beim Entwickeln Module, entsteht dabei ein Abhängigkeits-Graph oder -Diagramm. Über Import-Statements werden die Verbindungen zwischen verschiedenen Dependencies hergestellt. Über diese Statements weiß der Browser genau, welcher Code geladen werden muss. Ihr gebt dem Browser quasi eine Datei, über die er in den Dependency-Graphen einsteigen kann. Von dort aus kann er über weitere Import-Statements weiteren Code finden.

Die ESM-Syntax

Die Syntax zum Importieren eines Moduls sieht so aus:

import module from 'module-name'

zum Vergleich, in CommonJS sieht sie so aus:

const module = require ('module-name')

Ein Modul ist eine JS-Datei, die einen oder mehrere Values – Funktionen, Variablen oder Objekte – mittels des export-Keywords exportiert. Zum Beispiel so:

//lowercase.js

export default str => str.toLowerCase()

Dateien sind aber nichts, was der Browser sofort nutzen kann. Vorher muss er all diese Dateien in Datenstrukturen umwandeln. Diese Datenstrukturen werden Module-Records genannt. Diese Module-Records kann der Browser verstehen – über diesen Zwischenschritt findet er heraus, was es mit einer Datei auf sich hat. In einem nächsten Schritt müssen die Module-Records zu Modulinstanzen umgewandelt werden.

Bitte beachte unsere Community-Richtlinien

Wir freuen uns über kontroverse Diskussionen, die gerne auch mal hitzig geführt werden dürfen. Beleidigende, grob anstößige, rassistische und strafrechtlich relevante Äußerungen und Beiträge tolerieren wir nicht. Bitte achte darauf, dass du keine Texte veröffentlichst, für die du keine ausdrückliche Erlaubnis des Urhebers hast. Ebenfalls nicht erlaubt ist der Missbrauch der Webangebote unter t3n.de als Werbeplattform. Die Nennung von Produktnamen, Herstellern, Dienstleistern und Websites ist nur dann zulässig, wenn damit nicht vorrangig der Zweck der Werbung verfolgt wird. Wir behalten uns vor, Beiträge, die diese Regeln verletzen, zu löschen und Accounts zeitweilig oder auf Dauer zu sperren.

Trotz all dieser notwendigen Regeln: Diskutiere kontrovers, sage anderen deine Meinung, trage mit weiterführenden Informationen zum Wissensaustausch bei, aber bleibe dabei fair und respektiere die Meinung anderer. Wir wünschen Dir viel Spaß mit den Webangeboten von t3n und freuen uns auf spannende Beiträge.

Dein t3n-Team

Schreib den ersten Kommentar!

Melde dich mit deinem t3n Account an oder fülle die unteren Felder aus.

Bitte schalte deinen Adblocker für t3n.de aus!

Hey du! Schön, dass du hier bist. 😊

Bitte schalte deinen Adblocker für t3n.de aus, um diesen Artikel zu lesen.

Wir sind ein unabhängiger Publisher mit einem Team bestehend aus 65 fantastischen Menschen, aber ohne riesigen Konzern im Rücken. Banner und ähnliche Werbemittel sind für unsere Finanzierung sehr wichtig.

Danke für deine Unterstützung.

Digitales High Five,
Stephan Dörner (Chefredakteur t3n.de) & das gesamte t3n-Team

Anleitung zur Deaktivierung