mitmario.dev

CommonJS

Node.js Sandbox 3 Min Lesezeit 3 BeispieleLektion 1 von 7

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.

Eine Datei gibt etwas her
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.

Die Falle mit exports
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.

Eine Datei läuft nur einmal
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, kostenlos

Zu 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.