Webpack ist ein Front-End-Tool zum Laden/Verpacken von Ressourcen. Es führt eine statische Analyse basierend auf Modulabhängigkeiten durch und generiert dann gemäß den angegebenen Regeln entsprechende statische Ressourcen für diese Module. In diesem Artikel wird hauptsächlich der Kompilierungsprozess des Webpack-Quellcodes vorgestellt. Freunde, die ihn benötigen, können darauf verweisen.
Webpack ist derzeit das wichtigste Verpackungstool für Anwendungen, die auf React und Redux basieren. Ich denke, dass viele Anwendungen, die mit Angular 2 oder anderen Frameworks entwickelt wurden, auch Webpack verwenden.
Der Prozess dieses Abschnitts ist wie in der Abbildung dargestellt:
Jetzt haben wir offiziell mit dem Verpackungsprozess begonnen:
Compiler.prototype.run = (callback) => { const startTime = Date.now(); const onCompiled = (err, compilation) => { /**/ }; this.applyPluginsAsync("before-run", this, err => { if (err) return callback(err); this.applyPluginsAsync("run", this, err => { if (err) return callback(err); this.readRecords(err => { if (err) return callback(err); this.compile(onCompiled); }); }); }); }
Warum nicht das Compiler-Objekt einführen? Da es im Konstruktor keine Initialisierungsmethode gibt, handelt es sich lediglich um eine gewöhnliche Variablendeklaration, über die es nichts zu sagen gibt.
In der Ausführungsmethode wird zuerst applyPluginsAsync von tapable aufgerufen, um den Ereignisstrom vor der Ausführung auszuführen. Der Ereignisstrom ist wie folgt definiert:
// NodeEnvironmentPlugin compiler.plugin("before-run", (compiler, callback) => { if (compiler.inputFileSystem === inputFileSystem) inputFileSystem.purge(); callback(); });
In der Dateisystemmethode des Compilerobjekts In Nach dem Mounten des Plug-Ins wird der Vorlauf-Ereignisstrom eingefügt. Hier werfen wir zunächst einen Blick auf applyPluginsAsync (leicht modifiziert, um es an den Webpack-Quellcode anzupassen):
// tapable Tapable.prototype.applyPluginsAsync = (name, ...args, callback) => { var plugins = this._plugins[name]; if (!plugins || plugins.length === 0) return callback(); var i = 0; var _this = this; // args为[args,next函数] args.push(copyProperties(callback, function next(err) { // 事件流出错或者全部执行完后调用回调函数 if (err) return callback(err); i++; if (i >= plugins.length) { return callback(); } // 执行下一个事件 plugins[i].apply(_this, args); })); // 执行第一个事件 plugins[0].apply(this, args); };
Zu diesem Zeitpunkt diese Reihe von Ereignissen wurde in Abschnitt 8 nicht erwähnt. Hier ist eine kurze Erklärung der Flow-Trigger-Methode:
1. copyProperties wird zum Kopieren von Objekteigenschaften verwendet, ähnlich wie Object.assign. Hier werden jedoch zwei Funktionen übergeben nützt überhaupt nichts! ! ! ! ! (Ich habe damals keine Erklärung geschrieben, weil ich nicht wusste, welchen Nutzen die Objektkopiermethode hier hat)
2 Im Webpack ist args ein this, das auf den Kontext des Compilers verweist
3. In diesen Ereignisstrom eingefügte Ereignisse müssen die Rückrufmethode ausführen (wie im obigen Beispiel). Zu diesem Zeitpunkt wird nicht der externe Rückruf ausgeführt, sondern die nächste Funktion
4. Es gibt zwei Situationen, in denen der externe Rückruf ausgeführt wird und auf halbem Weg ein Fehler auftritt.
Die Bedeutung der in before-run eingefügten Funktionsparameter ist wie folgt folgt:
// before-run // compiler => this // callback => next (compiler, callback) => { if (compiler.inputFileSystem === inputFileSystem) inputFileSystem.purge(); callback(); }
Da es im Vorlauf nur ein Ereignis gibt, also vor dem Aufruf Nach der nächsten Methode des internen Rückrufs wird der externe Rückruf direkt aufgerufen, da i größer als die Ereignislänge ist.
Die Löschmethode hier haben wir schon einmal gesehen:
// NodeEnvironmentPlugin compiler.inputFileSystem = new CachedInputFileSystem(new NodeJsInputFileSystem(), 60000); // CachedInputFileSystem CachedInputFileSystem.prototype.purge = function(what) { this._statStorage.purge(what); this._readdirStorage.purge(what); this._readFileStorage.purge(what); this._readlinkStorage.purge(what); this._readJsonStorage.purge(what); }; // CachedInputFileSystem => Storage Storage.prototype.purge = function(what) { if (!what) { this.count = 0; clearInterval(this.interval); this.nextTick = null; this.data.clear(); this.levels.forEach(function(level) { level.clear(); }); } else if (typeof what === "string") { /**/ } else { /**/ } };
In einem Satz kann es wie folgt zusammengefasst werden: Alle zwischengespeicherten Daten im Paket löschen.
Da davon ausgegangen wird, dass es sich um das erste Mal handelt, gibt es hier keine tatsächliche Operation. Anschließend wird der externe Rückruf aufgerufen und der Ausführungsereignisstrom auf die gleiche Weise ausgelöst.
Es gibt nur eine Methode für den Laufereignisstrom, der vom CachePlugin-Plugin stammt:
Compiler.plugin("run", (compiler, callback) => { // 这个属性我暂时也不知道是啥 反正直接callback了 if (!compiler._lastCompilationFileDependencies) return callback(); const fs = compiler.inputFileSystem; const fileTs = compiler.fileTimestamps = {}; asyncLib.forEach(compiler._lastCompilationFileDependencies, (file, callback) => { // ... }, err => { // ... }); });
Wenn der Laufereignisstrom zum ersten Mal ausgelöst wird, ist die Eigenschaft undefiniert. Daher wird es direkt übersprungen, da ich es beim Betrachten des Quellcodes analysiert habe und daher nicht weiß, was es ist, haha.
Der nächste Rückruf ist dieser:
this.readRecords(err => { if (err) return callback(err); this.compile(onCompiled); });
Dies ist eine weitere Prototypmethode, der Quellcode lautet wie folgt:
Compiler.prototype.readRecords = (callback) => { // 这个属性也没有 if (!this.recordsInputPath) { this.records = {}; return callback(); } this.inputFileSystem.stat(this.recordsInputPath, err => { // ... }); }
Das erste Mal hier wird ebenfalls übersprungen und der Rückruf Wenn Sie sich den Quellcode ansehen, bedeutet dies wahrscheinlich, dass Sie einen Pfad übergeben, die darin enthaltenen Dateiinformationen lesen und in Datensätzen zwischenspeichern.
Springen Sie nun zwei Schritte und geben Sie direkt die Kompilierungsmethode des Prototyps ein. Sehen Sie sich diese Funktion in der Vorschau an:
Compiler.prototype.compile = (callback) => { const params = this.newCompilationParams(); // 依次触发事件流 this.applyPluginsAsync("before-compile", params, err => { if (err) return callback(err); this.applyPlugins("compile", params); const compilation = this.newCompilation(params); this.applyPluginsParallel("make", compilation, err => { if (err) return callback(err); compilation.finish(); compilation.seal(err => { if (err) return callback(err); this.applyPluginsAsync("after-compile", compilation, err => { if (err) return callback(err); return callback(null, compilation); }); }); }); }); }
Der Kernprozess des Kompilierens und Packens ist deutlich zu erkennen, und die Methode löst vor dem Kompilieren und Kompilieren aus , make, Ereignisfluss nach der Kompilierung und schließlich wird die Rückruffunktion aufgerufen.
Ich habe das Obige für Sie zusammengestellt und hoffe, dass es Ihnen in Zukunft hilfreich sein wird.
Verwandte Artikel:
So implementieren Sie eine Hintergrundvideo-Anmeldeseite mit Vue.js 2.0
Wie Sie Vue nutzen, um Zeit zu entwickeln Umbauanleitung?
Wie implementiert man eine Seitenanpassung in AngularJS?
Wie überwacht man window.resize in VueJs und wie implementiert man es konkret?
Detaillierte Interpretation des Konzepts des $window-Fensterobjekts in AngularJS
Wie implementiert man React-native Bridging Android und was sind die Besonderheiten? Schritte?
Das obige ist der detaillierte Inhalt vonDetaillierte Interpretation der im Webpack ausgeführten Eingabefunktion. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!