addEntry
EntryPlugin的注冊
webpack會從入口開始解析依賴。
-
WebpackOptionsApply
new WebpackOptionsApply().process(compiler, options); class WebpackOptionsApply {constructor () {}process () {// 注冊 EntryOptionPlugin new EntryOptionPlugin().apply(compiler);} }
-
EntryOptionPlugin
EntryOptionPlugin的作用是注冊compiler.hooks.entryOption鉤子,當鉤子被觸發的時候,調用EntryOptionPlugin.applyEntryOption方法注冊DynamicEntryPlugin或者EntryPluginclass EntryOptionPlugin {apply(compiler) {compiler.hooks.entryOption.tap("EntryOptionPlugin", (context, entry) => {// 調用靜態方法 applyEntryOptionEntryOptionPlugin.applyEntryOption(compiler, context, entry);return true;});}static applyEntryOption(compiler, context, entry) {if (typeof entry === "function") {// 動態入口const DynamicEntryPlugin = require("./DynamicEntryPlugin");new DynamicEntryPlugin(context, entry).apply(compiler);} else {// 普通入口const EntryPlugin = require("./EntryPlugin");for (const name of Object.keys(entry)) { for (const entry of desc.import) {new EntryPlugin(context, entry, options).apply(compiler);}}}} }
-
EntryPlugin
- 訂閱了compiler.hooks.compilation鉤子,觸發時設置EntryDependency的ModuleFactory normalModuleFactory工廠,這個用于創建入口模塊
- 訂閱compiler.hooks.make鉤子,觸發的時候調用compilation.addEntry方法,將入口模塊加載到factorizeQueue隊列,這樣依賴就啟動了以入口模塊為七點的模塊構建流程。
class EntryPlugin {constructor(context, entry, options) {}apply(compiler) {compiler.hooks.compilation.tap("EntryPlugin",(compilation, { normalModuleFactory }) => {compilation.dependencyFactories.set(EntryDependency,normalModuleFactory);});const { entry, options, context } = this;const dep = EntryPlugin.createDependency(entry, options);compiler.hooks.make.tapAsync("EntryPlugin", (compilation, callback) => {compilation.addEntry(context, dep, options, err => {callback(err);});});} }
-
EntryPlugin的觸發
調用compiler.run() -> compiler.compile()方法觸發compiler.hooks.make鉤子,進而觸發EntryPlugin鉤子
class Compiler {compile(callback) {this.hooks.beforeCompile.callAsync(params, err => {this.hooks.compile.call(params);this.hooks.make.callAsync(compilation, err => {})})}
}
流程為: npm run build -> webpack -> webpack-cli -> compiler.run() -> compiler.compile() -> compiler.hooks.make.callAsync() -> EntryPlugin -> compilation.addEntry()
compilation.addEntry方法的講解
方法參數
- context: 上下文目錄,構建中就是當前目錄的項目目錄
- entry: 入口對象,結合EntryPlugin可以看到傳入的路由,Entryplugin.createDependency方法返回值對象
- optionsOrName: 選項或者名字
- callback: entry的回調函數,用于和compiler通信進行后續的流程
class Compilation {addEntry(context, entry, optionsOrName, callback) {const options =typeof optionsOrName === "object"? optionsOrName: { name: optionsOrName };this._addEntryItem(context, entry, "dependencies", options, callback);}_addEntryItem(context, entry, target, options, callback) {}
}
方法邏輯
- 標準化處理options,根據optionsOrName格式化成不同的對象
- 調用compilation._addEntryItem()方法
compilation._addEntryItem
- context: webpack構建上下文目錄,以及項目目錄
- entry: 入口對象,上文中的EntryPlugin.createDependency()返回的EntryDependency類型的實例對象
- target: 目標類型,用于在entryData中分類類型進行緩存的標志
- options: webpack的配置對象或者是nameOptions對象,由compilation.addEntry標準化
- callback: 回調函數,用于和compiler進行通信使用
class Compilation {_addEntryItem(context, entry, target, options, callback) {// 根據options是否由name屬性或者是compilation.entries或者是compilation.globalEntry中嘗試獲取緩存的入口entryDataconst { name } = options;let entryData =name !== undefined ? this.entries.get(name) : this.globalEntry;// 沒有entryData的時候,會構建entryData對象,將其緩存到compilation.entries,另外entryData.dependency設置為初始的entry入口對象if (entryData === undefined) {entryData = {dependencies: [],includeDependencies: [],options: {name: undefined,...options}};entryData[target].push(entry);this.entries.set(name, entryData);} else {// 這里不成立,先忽略} // 觸發this.hooks.addEntry鉤子this.hooks.addEntry.call(entry, options);// this.addModuleTree方法this.addModuleTree(/* ... */);}
}
callback回調 => _addEntryItem的回調
addEntry(context, entry, optionsOrName, callback) {this._addEntryItem(context, entry, "dependencies", options, callback);
}
compilation.addModuleTree
- context: 上下文,當前項目的目錄
- dependency: 依賴對象
- contextInfo: 上下文對象
class Compilation {// ...addModuleTree({ context, dependency, contextInfo }, callback) {const Dep = dependency.constructor;const moduleFactory = this.dependencyFactories.get(Dep);this.handleModuleCreation({factory: moduleFactory,dependencies: [dependency],originModule: null,contextInfo,context},(err, result) => {if (err && this.bail) {} else if (!err && result) {callback(null, result);} else {callback();}});}
}
執行模塊以及其依賴的子模塊的構建,構建工作