Webpack は、フロントエンドのリソース読み込み/パッケージ化ツールです。モジュールの依存関係に基づいて静的分析を実行し、指定されたルールに従ってこれらのモジュールに対応する静的リソースを生成します。この記事では主に Webpack ソース コードのコンパイル プロセス、つまりエントリ関数の実行について紹介します。Webpack は現在、React と Redux をベースに開発されたアプリケーションの主要なパッケージング ツールです。 Angular 2 や他のフレームワークを使用して開発されたアプリケーションの多くも Webpack を使用していると思います。
このセクションのプロセスは次の図に示すとおりです:
これで、正式にパッケージ化プロセスに入りました。開始メソッドが実行されます:
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); }); }); }); }
コンパイラ オブジェクトを導入してみませんか?コンストラクターには初期化メソッドがなく、ただの普通の変数宣言なので、特に話すことはありません。
runメソッドでは、まずtapableのapplyPluginsAsyncを呼び出して実行前イベントフローを実行します。 イベントフローは以下のように定義されています:
// NodeEnvironmentPlugin compiler.plugin("before-run", (compiler, callback) => { if (compiler.inputFileSystem === inputFileSystem) inputFileSystem.purge(); callback(); });
コンパイラオブジェクトのファイルシステムメソッドのマウントプラグインでは、beforeは次のように定義されています。 injected -このイベント ストリームを実行します。ここでは、最初に applyPluginsAsync を見ていきます (Webpack ソース コードに適応するために若干の変更を加えています):
// 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); };
その時点では、このシリーズのイベント ストリーム トリガー メソッドについてはセクションで説明しませんでした。
1 、 copyProperties は、 Object.assign と同様に、オブジェクトのプロパティをコピーするために使用されます。 ただし、ここでは 2 つの関数が渡されますが、これはまったく役に立ちません。 ! ! ! ! (オブジェクトコピーメソッドがここで何に役立つかについていつも行き詰まっていたので、その時は説明を書きませんでした)
2. webpack では、args はコンパイラのコンテキストを指します
3.イベント ストリームに挿入されるイベントは、(上記の例のように) コールバック メソッドが実行されるとき、この時点で実行されるのは外部コールバックではなく、次の関数です
4.コールバックが実行されるか、途中でエラーが発生するか、すべてのイベントフローが実行されます
これは非常に明確です さて、before-runに注入される関数パラメータの意味は次のとおりです:
// before-run // compiler => this // callback => next (compiler, callback) => { if (compiler.inputFileSystem === inputFileSystem) inputFileSystem.purge(); callback(); }
イベントが1つしかないため実行前では、内部コールバックの次のメソッドを呼び出した後、i がイベントの長さより大きいため、外部コールバックが直接呼び出されます。
ここでのパージ方法は以前に見たことがありますので、ここで内容を確認してみましょう:
// 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 { /**/ } };
一言で言えば、それは次のとおりです: パッケージ内のキャッシュされたデータをすべてクリアします。
初回であることを想定しているため、ここでは実際の操作はありません。その後、外部コールバックが呼び出され、同じように実行イベント ストリームがトリガーされます。
CachePlugin プラグインからの実行イベント ストリームのメソッドは 1 つだけです:
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 => { // ... }); });
実行イベント ストリームが初めてトリガーされるとき、属性は未定義であるため、直接スキップされます。ソースコードを読みながら解析しているので、それが何なのかも分かりません(笑)。
次のコールバックはこれです:
this.readRecords(err => { if (err) return callback(err); this.compile(onCompiled); });
これは別のプロトタイプメソッドで、ソースコードは次のとおりです:
Compiler.prototype.readRecords = (callback) => { // 这个属性也没有 if (!this.recordsInputPath) { this.records = {}; return callback(); } this.inputFileSystem.stat(this.recordsInputPath, err => { // ... }); }
ここの初回もスキップしてコールバックを直接渡します。ソースコードを見ると、おそらくこれを渡します。ファイル情報はレコードにキャッシュされます。
次に、2 つのステップを続けてジャンプし、プロトタイプ メソッドのコンパイルを直接入力し、この関数をプレビューします:
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); }); }); }); }); }
コンパイルとパッケージ化のコア プロセスが明確に確認でき、コンパイル前、コンパイル、メイク、および後 -コンパイル イベントはメソッド ストリーム内でトリガーされ、最後にコールバック関数が呼び出されます。
上記は私があなたのためにまとめたものです。
関連記事:
Vue.js 2.0を使用して背景ビデオログインページを実装する方法Vueを使用して時間変換命令を開発する方法? angularjs でページ アダプテーションを実装するにはどうすればよいですか? VueJs で window.resize を監視する方法とそれを具体的に実装する方法? AngularJSの$windowウィンドウオブジェクトの概念の詳細な解釈ReactネイティブブリッジAndroidを実装する方法、具体的な手順は何ですか?以上がWebpack で実行されるエントリー関数の詳細な解釈の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。