以单入口entry配置为例,在EntryOptionPlugin插件中定义了,不同配置的入口应该调用何种插件进行解析。不同配置的入口插件中注册了对应的 make 事件回调函数,在make事件触发后被调用。
如下所示:
一个插件的apply方法是一个插件的核心方法,当说一个插件被调用时主要是其apply方法被调用。
EntryOptionPlugin 插件在webpackOptionsApply中被调用,其内部定义了使用何种插件来解析入口文件。
const SingleEntryPlugin = require("./SingleEntryPlugin"); const MultiEntryPlugin = require("./MultiEntryPlugin"); const DynamicEntryPlugin = require("./DynamicEntryPlugin"); module.exports = class EntryOptionPlugin { apply(compiler) { compiler.plugin("entry-option", (context, entry) => { function itemToPlugin(item, name) { if(Array.isArray(item)) { return new MultiEntryPlugin(context, item, name); } else { return new SingleEntryPlugin(context, item, name); } } // 判断entry字段的类型去调用不同的入口插件去处理 if(typeof entry === "string" || Array.isArray(entry)) { compiler.apply(itemToPlugin(entry, "main")); } else if(typeof entry === "object") { Object.keys(entry).forEach(name => compiler.apply(itemToPlugin(entry[name], name))); } else if(typeof entry === "function") { compiler.apply(new DynamicEntryPlugin(context, entry)); } return true; }); } };
entry-option 事件被触发时,EntryOptionPlugin 插件做了这几个事情:
判断入口的类型,通过 entry 字段来判断,对应了 entry 字段为 string object function的三种情况
每种不同的类型调用不同的插件去处理入口的配置。大致处理逻辑如下:
- 数组类型的entry调用multiEntryPlugin插件去处理,对应了多入口的场景
- function的entry调用了DynamicEntryPlugin插件去处理,对应了异步chunk的场景
- string类型的entry或者object类型的entry,调用SingleEntryPlugin去处理,对应了单入口的场景
【问题】entry-option 事件是在什么时机被触发的呢?
如下代码所示,是在WebpackOptionsApply.js中,先调用处理入口的EntryOptionPlugin插件,然后触发 entry-option 事件,去调用不同类型的入口处理插件。
注意:调用插件的过程也就是一个注册事件以及回调函数的过程。
WebpackOptionApply.js
// 调用处理入口entry的插件 compiler.apply(new EntryOptionPlugin()); compiler.applyPluginsBailResult("entry-option", options.context, options.entry);
前面说到,make事件触发时,对应的回调逻辑都在不同配置入口的插件中注册的。下面以SingleEntryPlugin为例,说明从 make 事件被触发,到编译结束的整个过程。