Fast alle Node.js -Entwickler können Ihnen sagen, was die Funktion "benötigt ()", aber wie viele von uns wissen wirklich, wie sie funktioniert? Wir verwenden es jeden Tag, um Bibliotheken und Module zu laden, aber sein Verhalten ist uns ein Rätsel.
Aus Neugier habe ich mich in den Kerncode des Knotens eingeteilt, um herauszufinden, was unter dem Motor passiert ist. Dies ist jedoch keine einzige Funktion. Ich habe Modul.js im Knotenmodulsystem gefunden. Die Datei enthält ein überraschend leistungsstarkes und relativ unbekanntes Kernmodul, das die Lade, Kompilierung und Zwischenspeicherung jeder Datei steuert. `erfordern ()`, seine Entstehung ist nur die Spitze des Eisbergs.
module.js
Die Codekopie lautet wie folgt:
Funktionsmodul (ID, Eltern) {
this.id = id;
this.exports = {};
this.Parent = Eltern;
// ...
In module.js spielt es hauptsächlich zwei Rollen innerhalb von Node.js. Erstens bietet es eine Grundlage für alle Node.js -Module. Jede Datei ist eine neue Instanz des Basismoduls neu und existiert auch nach der Ausführung der Datei. Aus diesem Grund können wir die Eigenschaften an modul.exports anbringen und bei Bedarf zurückgeben.
Die zweite Hauptaufgabe dieses Moduls besteht darin, den Modullastmechanismus des Knotens zu verarbeiten. Der unabhängige Betrieb der von uns verwendeten Funktion "Erforderliche" ist eigentlich ein abstraktes Konzeptmodul. Erregt, das selbst nur eine einfache Kapselung über das Modul._Load -Funktion ist. Diese Lastmethode behandelt das tatsächliche Laden jeder Datei und startet unsere Reise dorthin.
Module._load
Die Codekopie lautet wie folgt:
Module._load = function (request, übergeordnet, ismain) {
// 1.. MODULE._Cache für das zwischengespeicherte Modul.
// 2. Erstellen Sie eine neue Modulinstanz, wenn der Cache leer ist.
// 3.. Speichern Sie es im Cache.
// 4. Anrufmodul.load () mit dem angegebenen Dateinamen.
// Aufrufe module.comPile (), nachdem der Dateiinhalt gelesen wurde.
// 5. Wenn ein Fehler beim Laden/Analysieren der Datei vorhanden ist,
// Löschen Sie das schlechte Modul aus dem Cache
// 6. return module.exports
};
Modul._load ist für das Laden neuer Module und das Verwalten von Modul -Caches verantwortlich. Cache geladen jedes Modul reduziert die Anzahl der Lesevorgänge redundanter Dateien und kann Ihre Anwendung erheblich beschleunigen. Darüber hinaus ermöglicht die gemeinsame Modulinstanz Module mit Singleton -Eigenschaften im Staat im Projekt.
Wenn ein Modul im Cache nicht vorhanden ist, erstellt modul._load ein neues Basismodul für die Datei. Anschließend wird das Modul angegeben, den Inhalt der neuen Datei zu lesen, bevor sie an modul._compile gesendet werden. [1]
Wenn Sie feststellen, dass Schritt 6 oben angegeben ist, werden Sie angezeigt, dass Module.exports an den Benutzer zurückgegeben wurde. Aus diesem Grund verwenden Sie, wenn Sie die Nutzung der öffentlichen Schnittstelle definieren, Exporte und modul.exports, da modul._load als nächstes den Inhalt der Forderung zurückgibt. Ich war überrascht, dass es hier keine Merkmale mehr gab, aber es wäre besser, wenn es gäbe.
module._compile
Die Codekopie lautet wie folgt:
Module.Prototype._Compile = Funktion (Inhalt, Dateiname) {
// 1. Erstellen Sie die eigenständige Funktion, die modul.require aufruft.
// 2. Befestigen Sie andere Helfermethoden, um sie zu verlangen.
// 3.hülle den JS -Code in eine Funktion, die unsere Forderung liefert.
// Modul usw. Variablen lokal zum Modulbereich.
// 4. Führen Sie diese Funktion aus
};
・ Hier passiert das wahre Wunder. Erstens wird für das Modul eine spezielle, unabhängige operative Erfordernisse erstellt. Dies ist eine Funktion, die wir brauchen und mit der wir alle vertraut sind. Die Funktion selbst ist nur eine Kapselung im Modul.require, die auch einige weniger bekannte Hilfsmethoden enthält, die für uns einfach zu verwenden sind:
・ Erfordert (): Laden Sie ein externes Modul
・ Fordert.resolve (): An einem Modulnamen auf seinen absoluten Pfad analysieren
・ Bedarf.Main: Hauptmodul
・ Erfordern.Cache: Alle zwischengespeicherten Modulen
・ ・ ・ ・ Fordert.exessions: Eine Kompilierungsmethode, die für jeden gültigen Dateityp gemäß seiner Erweiterung verwendet werden kann
Sobald der Forderung fertig ist, wird der gesamte geladene Quellcode in einer neuen Funktion eingekapselt, sodass er Anforderungen, Modul, Exporte und alle anderen exponierten Variablen als Parameter akzeptieren kann. Dies ist eine Funktion, die nur zur Einkapselung von Modulen erstellt wurde, um Konflikte mit der Node.js -Umgebung zu verhindern.
Die Codekopie lautet wie folgt:
(Funktion (exportiert, erfordern, modul, __FileName, __DIRNAME) {{
// Ihr Code hier injiziert!
});
Die Methode modul._compile wird synchron ausgeführt, sodass der Anruf bei Module._Load nur warten kann, bis der Code ausgeführt wird und moduls.exprts an den Benutzer zurückgibt.
abschließend
Wir haben also bereits den vollständigen Code des Forderung verstanden und haben ein vorläufiges Verständnis dafür, wie er funktioniert.
Wenn Sie es den ganzen Weg getan haben, sind Sie bereit für das letzte Geheimnis: Erfordernst ('Modul'). Dies ist korrekt, das Modulsystem selbst kann über das Modulsystem geladen werden. Beginn. Dies mag seltsam klingen, aber es ermöglicht den Benutzerraum, mit Modul -Ladesystemen zu interagieren, ohne sich in den Kern von Node.js zu befreien. Beliebte Module sind alle so gebaut. [2]
Wenn Sie mehr wissen möchten, überprüfen Sie bitte den Quellcode modul.js. Es gibt immer noch viele Dinge, die Sie für eine Weile Kopfschmerzen haben werden. Der erste kann mir sagen, was node_module_contexts lautet "und warum es hinzugefügt wird, kann Bonuspunkte erhalten :)
[1] Die Methode modul._compile wird nur zum Ausführen von JavaScript -Dateien verwendet. Die JSON -Datei muss über JSON.Parse () analysiert und zurückgegeben werden
[2] Beide Module basieren jedoch auf privaten Modulmethoden wie modul._resolvelookuppaths und modul._findpath. Sie können denken, dass dies nicht viel besser ist ...