webpack 插件机制 理解

247 阅读2分钟

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 允许你通过回调函数的参数访问事件的生产者。