Abschnitt 2 · Lektion 5
Wie Node ein Modul findet
Cannot find module ist die Fehlermeldung, die dich in Node am häufigsten begrüßt. Sie ist auch die
undankbarste, weil sie dir sagt, dass etwas fehlt, aber nicht, wo Node gesucht hat.
Diese Lektion räumt das auf. Danach kannst du vorhersagen, wo Node nachschaut, und die Meldung sagt dir dann von selbst, was los ist.
Drei Arten von Angaben
Was zwischen den Anführungszeichen steht, nennt sich Spezifizierer. Node schaut sich den Anfang an und entscheidet daran, wie gesucht wird.
Fängt es mit ./ oder ../ an, ist es ein Pfad. Gesucht wird relativ zu der Datei, in der der
Import steht, nicht relativ zum Arbeitsverzeichnis. Das ist derselbe Unterschied wie in der vorigen
Lektion, nur diesmal nimmt Node ihn dir ab.
Fängt es mit node: an, ist es eingebaut. Node schaut gar nicht auf die Festplatte.
Alles andere ist ein Paket. Also ein Name ohne Punkt und ohne Schrägstrich am Anfang, wie
express oder slugify. Danach wird in node_modules gesucht.
export function rechne(zahl) {
return zahl * zahl;
} import { readFile } from "node:fs/promises";
import { rechne } from "./lib/rechnen.mjs";
console.log("eingebaut:", typeof readFile);
console.log("relativ:", rechne(4)); Wie die Suche nach einem Paket abläuft
Bei einem Paketnamen schaut Node zuerst in das node_modules neben der Datei. Findet es dort nichts,
geht es einen Ordner nach oben und schaut wieder. Und noch einen. Und so weiter, bis zur Wurzel des
Dateisystems.
Das erklärt eine Beobachtung, über die man sonst stolpert: Eine Datei tief unten in
src/routen/admin/ findet ein Paket, obwohl dort weit und breit kein node_modules liegt. Es liegt
oben im Projektstamm, und Node hat sich hochgearbeitet.
Für Pakete gibt es noch eine zweite Schicht. In der package.json eines Pakets kann ein Feld
"exports" stehen, und darin legt der Autor fest, welche Dateien von außen überhaupt erreichbar sind
und unter welchem Namen. Deshalb funktioniert import x from "paket/extra" bei manchen Paketen und
bei anderen nicht. Mehr brauchst du dazu vorerst nicht zu wissen.
Die vier Ursachen, in der Reihenfolge ihrer Häufigkeit
Ein Tippfehler. Unspektakulär, aber es ist wirklich die Nummer eins. Lies den Pfad in der Fehlermeldung Zeichen für Zeichen, sie zeigt dir genau, wonach gesucht wurde.
Die vergessene Dateiendung. In ESM ist sie Pflicht, und das ist die Gewohnheit, die aus Bündler-Projekten mitkommt.
export function rechne(zahl) {
return zahl * zahl;
} // Die Datei liegt in lib/, hier fehlt der Ordner im Pfad.
import { rechne } from "./rechnen.mjs";
console.log(rechne(4)); Hier fehlt nicht die Endung, sondern der Ordner. Die Fehlermeldung nennt trotzdem genau den Ort, an dem gesucht wurde, und dort liegt eben nichts. Diese Zeile zu lesen ist schneller als zu raten.
Ein vergessenes npm install. Steht der Name ohne ./ da und meldet Node
Cannot find package, dann hat es in node_modules gesucht und nichts gefunden. Meistens, weil das
Projekt frisch geklont und noch nicht installiert wurde.
Groß- und Kleinschreibung. Der Fall, der dich am teuersten zu stehen kommt.
export function rechne(zahl) {
return zahl * zahl;
} // Die Datei heißt rechnen.mjs, hier steht Rechnen.mjs.
import { rechne } from "./lib/Rechnen.mjs";
console.log(rechne(4)); Auf macOS und unter Windows unterscheidet das Dateisystem meistens nicht zwischen Groß- und
Kleinschreibung. Rechnen.mjs findet dort also die Datei rechnen.mjs, und dein Programm läuft.
Linux unterscheidet sehr wohl, und auf Linux läuft dein Server. Das Ergebnis ist ein Fehler, der
ausschließlich in der Produktion auftritt und den du lokal nicht nachstellen kannst.
Deshalb die Empfehlung: Halte dich bei Dateinamen an eine Schreibweise und bleib dabei. Kleinbuchstaben mit Bindestrichen sind die üblichste, und sie hat den Vorteil, dass es nichts zu verwechseln gibt.
Zum Mitnehmen
Ein Pfad mit ./ am Anfang meint eine Datei neben dir. Derselbe Name ohne ./ meint ein Paket. Das ist kein Schreibstil, sondern eine andere Suche.
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, auf dem Server geprüft
Öffnet sich mit dem Basis Konto.