webpack插件机制是整个webpack工具的骨架,而webpack本身也是利用这套插件机制构建出来的。
插件概念
专注处理webpack在编译过程中的某个特定的任务的功能模块,成为插件。一个完成的webpack插件需要满足以下特征:
- 是一个独立的模块
- 模块对外暴露一个js函数
- 函数的原型上定义了一个apply方法,app方法入参是compiler对象
- apply函数中需要有通过compiler对象挂载的webpalc事件钩子,钩子回调用能拿到当前编译的compilation对象。
- 完成自定义子编译流程,并处理compilation对象。
- 如果异步编译插件的话,数据处理完成后执行 callback 回调。
webpack插件基本模型
// 1、BasicPlugin.js 文件(独立模块)
// 2、模块对外暴露的 js 函数
class BasicPlugin{
//在构造函数中获取用户为该插件传入的配置
constructor(pluginOptions) {
this.options = pluginOptions;
}
//3、原型定义一个 apply 函数,并注入了 compiler 对象
apply(compiler) {
//4、挂载 webpack 事件钩子(这里挂载的是 emit 事件)
compiler.plugin('emit', function (compilation, callback) {
// ... 内部进行自定义的编译操作
// 5、操作 compilation 对象的内部数据
console.log(compilation);
// 6、执行 callback 回调
callback();
});
}
}
// 7、暴露 js 函数
module.exports = BasicPlugin;
apply 方法源码:
const webpack = (options, callback) => {
...
for (const plugin of options.plugins) {
plugin.apply(compiler);
}
...
}
入参Compiler对象解释
compiler对象是webpacl的编译器对象,会在启动webpack的时候被一次性的初始化,compiler对象中包含了所有webpacl可自定义操作的配置,例如:loader的配置,plugin的配置,entry的配置等。相当于通过compiler对象拿到了webpack的主环境所有的信息。
区分Compilation 对象
compilation 实例继承于 compiler, compilation 对象代表了一次单一的版本 webpack 构建和生成编译资源。 当每检测到一个文件变化,会触发一次新的编译,从而生成一组新的编译资源以及新的Compilation 对象。一个Compilation 对象,包含了当前的模块资源、编译生成资源、变化的文件、以及 被跟踪依赖的状态信息。
Compiler 和 Compilation 的区别在于: Compiler 代表了整个 Webpack 从启动到关闭的生命周期,而 Compilation 只代表一次新的编译。
Tapable & Tapable 实例
webpack 的插件架构主要基于 Tapable 实现的,Tapable 是 webpack 项目组的一个内部库,主要是抽象了一套插件机制。Tapable 能够让我们为 javaScript 模块添加并应用插件。它可以被其它模块继承或混合。它类似于 NodeJS 的 EventEmitter 类,专注于自定义事件的触发和操作。 除此之外, Tapable 允许你通过回调函数的参数访问事件的生产者。