Heim > Artikel > Web-Frontend > Eine eingehende Untersuchung der Modularisierungs- und Lademethoden von seajs_Seajs
Seitdem ich es verwende, habe ich etwas über den Quellcode von Seajs erfahren. Hier ist mein Verständnis der folgenden Fragen:
1. Wie implementiert die Methode require(XXX) von seajs das Laden von Modulen?
2. Warum müssen Sie vorladen?
3. Warum benötigen Sie Build-Tools?
4. Was sind die Unterschiede zwischen dem Code vor und nach dem Erstellen und warum machen Sie das?
Frage 1: Wie implementiert die Methode require(XXX) von SeaJs das Laden von Modulen?
Die Codelogik ist ziemlich kompliziert. Das Verständnis des Quellcodes finden Sie am Ende des Artikels. Hier gehen wir kurz auf die Logik des Modulladens ein:
1. Beginnen Sie über den Methodeneintrag seajs.use mit dem Laden des verwendeten Moduls.
2. Das verwendete Modul darf zu diesem Zeitpunkt nicht im Mod-Cache vorhanden sein. seajs erstellt einen neuen Mod und gibt ihm einen Anfangsstatus.
3. Führen Sie die mod.load-Methode aus
4. Gehen Sie nach einer Reihe von Logikvorgängen zur Methode seajs.request und fordern Sie die Moduldatei an. Nachdem das Modul geladen ist, wird die Methode define ausgeführt.
5. Die Methode define analysiert und extrahiert die abhängigen Module des Moduls und speichert sie. Die Factory wird zwischengespeichert, aber nicht ausgeführt.
6. Die abhängigen Module des Moduls werden erneut geladen. Wenn noch abhängige Module vorhanden sind, wird das Laden fortgesetzt. Bis alle abhängigen Module geladen sind.
7. Nachdem alle Module geladen sind, führen Sie den Rückruf der use-Methode aus.
8. Die interne Logik des Moduls wird vom Callback ausgeführt. Die require-Methode wird nur während dieses Prozesses ausgeführt.
Frage 2: Warum ist eine Vorspannung erforderlich?
Wir sehen, dass die Methode seajs.use den Rückruf tatsächlich ausführt, nachdem alle abhängigen Module geladen wurden. Es versteht sich, dass vor der Ausführung des Geschäftslogikcodes alle abhängigen Modulcodes vorab geladen werden müssen. Warum gibt es also eine solche Logik, die zuerst vorgeladen werden muss?
Die Antwort liegt in der Ausführungsmethode der Anforderungsmethode, die auf andere Modulmethoden im Logikcode verweist:
var mod = require(id);
Diese Syntax bestimmt, dass der Erwerb des Mods ein synchroner Ausführungsprozess ist. Wenn der Modulcode zuvor nicht vorgeladen wurde, kann er nur mit der Rückrufmethode für asynchrones Laden implementiert werden, dann ist die gesamte Seajs-Ausführungslogik vollständig etwas anderes. Aufgrund der Asynchronität verstehen Sie die Ausführungsreihenfolge der Module nicht und die Logik wird schwer zu steuern sein.
Frage 3: Warum benötigen Sie Build-Tools?
Sie können sehen, dass jedes abhängige Modul vor dem Erstellen separat geladen wird. Dadurch werden zu viele Modulanforderungen generiert, was sich negativ auf die Leistung beim Laden der Seite auswirkt. Build-Tools sind im Wesentlichen darauf ausgelegt, das Problem des kombinierten Ladens von Modulen zu lösen.
Frage 4: Was sind die Unterschiede zwischen dem Code vor und nach dem Erstellen und warum machen wir das?
Was genau macht das Build-Tool? Wir sagen, dass es im Wesentlichen darum geht, das Problem des Code-Merge-Ladens zu lösen. Was bedeutet es also, einfach verschiedene Moduldateien in einer Datei zusammenzuführen?
Natürlich nicht. Probieren Sie es aus. Wenn Sie einfach mehrere Moduldateien zu einer Datei zusammenführen, werden Sie feststellen, dass diese Datei nicht normal ausgeführt werden kann.
Der Grund liegt in der Implementierung der Methode define.
Seajs empfiehlt, beim Definieren eines Moduls nur den Factory-Parameter in der Methode define zu übergeben. Rückblickend auf die Definitionsmethode: Wenn keine ID (vorübergehend äquivalent zur URL des Moduls) übergeben wird, wird die Methode getCurrentScript() verwendet, um den URL-Pfad der aktuell ausgeführten Moduldatei abzurufen, und dann wird dieser Pfad verwendet kann zusammen mit dem Modul selbst als Schlüsselwert für zwischengespeicherte Mods verwendet werden. Der entscheidende Punkt hierbei ist, dass der Modul-Caching-Mechanismus innerhalb des gesamten SeaJS tatsächlich auf der URL jedes Moduls als Cache-Schlüssel basiert. Die Methode require(id) kommt letztendlich über den URL-Schlüsselwert. Die Methode require(id) verwendet letztendlich den URL-Schlüsselwert, um das entsprechende Modul in CachedMods zu finden. Dieser Schlüsselwert kann nicht wiederholt werden und es dürfen keine Fehler gemacht werden, da sonst die entsprechende Beziehung zwischen den Modulen verwirrt wird. Wenn mehrere Moduldateien a, b und c einfach zu einer Zieldatei x zusammengeführt werden, kann getCurrentScript () nur den Pfad von x ermitteln, und die Schlüsselwerte der drei Module können nicht unterschieden werden, und die Ausführung wird definitiv ausgeführt falsch.
Wenn Sie also mehrere Moduldateien zusammenführen möchten, müssen Sie für jedes Modul die URL angeben. Das heißt, die Methode define muss den Parameter id übergeben. Wenn die ID übergeben wird, wandelt SeaJs die ID in eine URL um und verwendet sie als Cache-Schlüssel.
Wenn nur ID und Factory übergeben werden, also define(id, Factory), dann deps = undefiniert, führt die Methode define die Methode parseDependencies(factory.toString()) aus, um die abhängigen Module in der Factory zu extrahieren. Anschließend wird der Modulpfad analysiert und die Logik jedes Moduls einzeln online geladen. Zu diesem Zeitpunkt geht die Bedeutung des kombinierten Ladens verloren.
Für das Merge-Laden muss die Methode „define“ die drei Parameter „id“, „deps“ und „factory“ korrekt übergeben, um korrekt ausgeführt zu werden.
Die sogenannte CMD-Moduldefinitionsmethode von Seajs ermutigt jeden, während der Modulschreibphase nur einen Parameter, Factory, zu übergeben, und die anderen beiden Parameter werden in der späteren Codekonstruktionsphase generiert. Das Obige erklärt, warum diese beiden Parameter nach dem Bau notwendig sind.
Der Grund, warum empfohlen wird, beim Definieren eines Moduls nur die Factory zu übergeben, liegt meiner Meinung nach hauptsächlich daran, dass die manuell übergebenen ID- und Deps-Parameter äußerst fehleranfällig und umständlich zu verwalten sind. Tools können die Effizienz verbessern und korrekte Parameter sicherstellen.
Anhang: Verständnis der Hauptcodelogik von Seajs.
Hinweis: Die Quellcodeversion ist Sea.js 2.3.0
1. Schauen wir uns zunächst an, was die Methode define bewirkt
Module.define = Funktion (ID, Deps, Factory)
Die Methode define unterstützt drei Parameter. Darunter sind ID und Deps optional. ab Werk erforderlich. Der Code wird durch die folgende Logik gesteuert:
Deps ist jedoch tatsächlich notwendig, da Seajs wissen muss, von welchen Modulen jedes Modul abhängt, sonst kann es nicht geladen werden.
Wenn es sich bei der Factory also um eine Funktion handelt und Deps nicht aktiv übergeben werden, müssen Sie die Methode parseDependencies verwenden, um die abhängigen Module in der Factory zu analysieren.
Die Hauptaufgabe der parseDependencies-Methode besteht darin, einen regulären Ausdruck zu verwenden, um das XXX in allen require(XXX) im Funktionskörper zu extrahieren. Dies sind alle Module, von denen diese Funktion abhängt.
Die Methode selbst ist nicht kompliziert, aber dieser reguläre Ausdruck ist nicht einfach:
Speichern Sie nach der Analyse der Deps die Moduldefinition im Cache:
Beachten Sie, dass wir feststellen werden, dass die Methode define nur Module analysiert und Module speichert und keine Module ausführt.
2. Die eigentliche Ausführung des Moduls erfolgt in der require-Methode. Schauen wir uns als nächstes „require“ an.
Kurz gesagt besteht die Anforderungsmethode darin, das entsprechende Modul im Modulcache zu finden, in dem die Definitionsdefinition basierend auf der ID gespeichert ist, und es auszuführen, um die von der Moduldefinition zurückgegebene Methode zu erhalten:
In diesem ganzen großen Schritt gibt es einen sehr kritischen Schritt, der im Detail erklärt werden muss:
Module.get(require.resolve(id)).
Wenn Sie ein Modul benötigen, müssen Sie es zuerst finden. Die Module.get-Methode spielt diese Rolle.
Wenn keine zwischengespeicherten Mods vorhanden sind, erstellen Sie ein neues Modul und speichern Sie es in zwischengespeicherten Mods:
Die Methoden define und rquire scheinen nicht kompliziert zu sein. Der Hauptgrund für Seajs ist, dass die Modulladelogik etwas kompliziert ist.
3. Der eigentliche Einstiegspunkt für die Seajs-Ausführung ist die use-Methode:
Durch die Verwendungsmethode werden das Laden und die Ausführung des Moduls ausgehend von den IDs hier ausgelöst.
Sie können sehen, dass der entscheidende Punkt beim Laden in der mod.load-Methode liegt.
Der Code der Lademethode ist etwas lang. Die Hauptlogik besteht darin, festzustellen, ob der aktuelle Status des Mods geladen ist oder geladen wird.
In der Komfortfunktion des Moduls können wir sehen, dass der Standardwert des Status 0 ist.
Neue Module, die nicht geladen wurden, sind also hier: mod.status = STATUS.LOADING Der Status wird auf Laden gesetzt und die anschließende Ladelogik wird ausgeführt.
Der nächste Schritt besteht darin, die Abhängigkeits-URLs des Moduls abzurufen
mod.resolve-Methode:
Die Module.resolve-Methode wandelt im Wesentlichen relative Pfade, konfigurierte Pfade, Aliase usw. in einen absoluten Pfad um. Kein Code mehr gepostet.
Ladestatus des Moduls aktualisieren.
Logik zum Laden von Modulen:
Hauptsächlich die m.fetch-Methode, andere darin enthaltene Logik wird hier übersprungen.
Sie können sehen, dass seajs.request schließlich die Moduldatei lädt:
Nachdem alle abhängigen Module geladen wurden, führen Sie die Onload-Methode des Mods aus
Hier ist die mod.onload()-Methode
An diesem Punkt haben Sie fast die Kernlogik von Seajs gesehen. Als Referenz: Wenn Sie ein unklares Verständnis oder einen ungenauen Ausdruck haben, können Sie dies gerne gemeinsam besprechen.
Das Obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, er gefällt Ihnen allen.