Abschnitt 2 · Lektion 1
CommonJS
Im Browser hast du mehrere Dateien über mehrere <script>-Tags in eine Seite geholt, und alles, was
darin stand, lag danach im selben Raum. In Node gibt es keine Seite, in die man etwas hineinhängen
könnte. Stattdessen holt sich eine Datei aktiv, was sie braucht.
Es gibt dafür zwei Systeme. Das ältere heißt CommonJS und arbeitet mit require und
module.exports. Das neuere heißt ESM und ist Thema der nächsten Lektion.
Warum wir mit dem alten anfangen
Weil du es lesen können musst. CommonJS steht in jedem zweiten Projekt, in fast jeder Stack-Overflow-Antwort und in so gut wie jedem Tutorial, das älter als drei Jahre ist. Wer damit nichts anfangen kann, versteht die Hälfte des Bestands nicht.
Geschrieben wird in diesem Kurs ab der nächsten Lektion trotzdem ESM. Aber lesen können ist keine Nebensache, sondern der Normalfall im Beruf: Du landest ständig in Code, den jemand anders vor Jahren angefangen hat.
Hergeben und holen
Eine Datei ist in Node erst einmal für sich. Was darin steht, sieht sonst niemand, auch keine Datei
im selben Ordner. Erst module.exports macht etwas nach außen sichtbar.
function verdoppeln(zahl) {
return zahl * 2;
}
const gruss = "Hallo aus mathe.js";
module.exports = { verdoppeln, gruss }; const mathe = require("./mathe.js");
console.log(mathe.gruss);
console.log(mathe.verdoppeln(21));
const { verdoppeln } = require("./mathe.js");
console.log(verdoppeln(5)); module.exports ist eine ganz normale Zuweisung. Du legst dort ab, was andere benutzen dürfen,
meistens ein Objekt mit mehreren Einträgen. Auf der anderen Seite steht require, und was es
zurückgibt, ist genau das Objekt, das die andere Datei abgelegt hat.
Ob du es als Ganzes entgegennimmst oder gleich auseinandernimmst, ist Geschmackssache. Beide Wege im Beispiel liefern dasselbe.
Der Punkt vor dem Schrägstrich
require("./mathe.js") beginnt mit ./, und das ist kein Schmuck. Der Punkt sagt: such im selben
Ordner wie ich. Ohne ihn wäre mathe ein Paketname, und Node würde in node_modules suchen statt
neben der Datei. Warum das so ist und wo Node überall nachschaut, klärt Lektion 5 dieses Abschnitts.
Die Dateiendung darfst du in CommonJS weglassen, require("./mathe") funktioniert genauso. Gewöhn
dir trotzdem an, sie zu schreiben: In ESM ist sie Pflicht, und ein Kopf voller Ausnahmen ist
anstrengender als eine Gewohnheit.
exports ist eine Abkürzung, und sie hat eine Kante
Neben module.exports gibt es die Kurzform exports.name = .... Sie tut dasselbe, solange du an
das vorhandene Objekt etwas anhängst. Sobald du exports komplett neu belegst, passiert nichts
mehr.
exports.eins = "das kommt an";
// Das hier belegt nur die lokale Variable neu.
exports = { zwei: "das kommt nicht an" }; const falle = require("./falle.js");
console.log(falle);
console.log(falle.zwei); Der Grund ist unspektakulär: exports ist am Anfang nur eine zweite Variable, die auf dasselbe
Objekt zeigt wie module.exports. Hängst du etwas an das Objekt an, sehen es beide. Weist du
exports etwas Neues zu, zeigt sie woanders hin, und module.exports bleibt unbeeindruckt.
Herausgegeben wird immer nur, was in module.exports steht.
Merk dir die praktische Regel: Wenn du ein ganzes Objekt herausgeben willst, schreib
module.exports. Für einzelne Einträge ist exports.name in Ordnung.
require passiert sofort, und nur einmal
Zwei Eigenschaften, die zusammengehören und beide gern übersehen werden.
Erstens ist require synchron. Die Zeile lädt die andere Datei nicht irgendwann im Hintergrund,
sondern führt sie auf der Stelle von oben bis unten aus und geht erst dann weiter. Alles, was in der
anderen Datei auf oberster Ebene steht, passiert also in dem Moment, in dem du sie einbindest.
Zweitens merkt Node sich das Ergebnis.
console.log("zaehler.js wird ausgeführt");
let stand = 0;
module.exports = {
hoch() {
stand += 1;
return stand;
},
}; const a = require("./zaehler.js");
const b = require("./zaehler.js");
console.log(a.hoch());
console.log(b.hoch());
console.log(a === b); Beim zweiten require derselben Datei passiert gar nichts mehr. Node gibt dasselbe Objekt noch
einmal heraus, das es beim ersten Mal bekommen hat. Deshalb steht die Meldung aus zaehler.js nur
einmal da, und deshalb zählt der Stand über beide Variablen hinweg weiter.
Das ist selten ein Problem und manchmal genau das, was man will: Eine Datenbankverbindung oder eine eingelesene Konfiguration soll es nur einmal geben, auch wenn zehn Dateien sie anfordern. Wissen solltest du es trotzdem, denn wenn du ein Modul schreibst, das beim Laden etwas verändert, tut es das genau einmal und nicht bei jedem Aufruf.
Zum Mitnehmen
require führt die Datei sofort aus, nicht erst beim ersten Zugriff. Und nur beim ersten Mal.
Jetzt du
Basis Konto, kostenlosZu dieser Lektion gehört eine Aufgabe. Du schreibst den Code selbst, und nach jedem Lauf sagt dir eine Prüfliste, was schon stimmt.
Dafür brauchst du das Basis Konto. Es kostet nichts, und ein Passwort gibt es auch nicht.
In diesem Kurs läuft dein Code auf einem Server. Dafür hat das Basis Konto 1 Stunde im Monat, mehr Zeit gibt es mit dem Premium Konto.
Was in dieser Lektion steckt
-
Artikel mit 3 Beispielen zum Ausprobieren
Steht hier, ohne Konto lesbar.
-
Aufgabe, dein Code läuft auf einem Server
Öffnet sich mit dem Basis Konto.