实现一个简单的webpack的plugin插件

1,770 阅读2分钟

简介

本次分享如何实现一个简单的plugin插件

创建自定义plugin步骤

  • 声明一个js函数或class类(大驼峰命名)
  • 定义一个原型方法apply,apply方法接收一个compiler对象,我们可以在apply方法中调用compiler对象的hooks事件。使用compilation操纵修改 webpack 内部实例特定数据。
  • 在功能完成后调用 webpack 提供的回调。
callback();
// or
callback(error);

知识准备

创建自定义plugin步骤我们是知道了,那compiler对象是什么?我们又如何操作 webpack 内部实例特定数据呢?

compiler

Compiler是 webpack 的主要引擎,它通过 CLI(通常我们在webpack.config.js配置的参数) 传递的所有选项, 或者 Node API,创建出一个 compilation 实例。它扩展自 Tapable 类,用来注册调用插件。

compiler暴露的生命周期hooks函数

  • compiler.hooks.emit,生命周期:输出 asset 到 output 目录之前执行。
 compiler.hooks.emit.tap('clean-webpack-plugin', compilation => {
   // 执行操作
 });
  • compiler.hooks.done,生命周期:在 compilation 完成时执行
 compiler.hooks.done.tap('clean-webpack-plugin', stats => {
   // 执行操作
 });
  • compiler.hooks.shouldEmit,生命周期:在输出 asset 之前调用。返回一个布尔值,告知是否输出。
compiler.hooks.shouldEmit.tap('clean-webpack-plugin', (compilation) => {
  // 返回 true 以输出 output 结果,否则返回 false
  return true;
});

compiler的钩子函数有很多,我们不需要都去了解,在需要用的时候去查API即可: webpack.docschina.org/api/compile…

compilation

compilation模块会被compiler用来创建新的 compilation 对象。 compilation实例能够访问所有的模块和它们的依赖,它会对应用程序的依赖图中所有模块, 进行字面上的编译,在编译阶段,模块会被加载(load)、封存(seal)、优化(optimize)、 分块(chunk)、哈希(hash)和重新创建(restore)。

compilation暴露的生命周期hooks函数

  • compilation.hooks.buildModule,生命周期:在模块构建开始之前触发,可以用来修改模块。
compilation.hooks.buildModule.tap(
  'SourceMapDevToolModuleOptionsPlugin',
  (module) => {
    module.useSourceMap = true;
  }
);
  • compilation.hooks.failedModule,生命周期:模块构建失败时执行。
compilation.hooks.failedModule.tap(
  'SourceMapDevToolModuleOptionsPlugin',
  (module, error) => {
    // 执行操作
  }
);

不一一例举,附上API文档:webpack.docschina.org/api/compila…

compilation 对象方法

  • compilation.getStats(),返回当前编译的状态对象
  • compilation.addEntry(),为编译添加入口。
  • compilation.finish(),完成编译并调用给定的回调。 不一一例举,附上API文档:webpack.docschina.org/api/compila…

基于以上的基础一个简单的plugin插件就出来啦!

class CleanWebpackPlugin {
    // 构造函数
    // 查看options具体参数: https://github.com/johnagan/clean-webpack-plugin#options-and-defaults-optional
    constructor(options) {
        console.log(options, 'options');
         this.outputPath = '';
    }

    apply(compiler) {
        console.log(compiler, 'compiler')
        // compiler.options获取config文件或shell命令初始化的配置信息
        this.outputPath = compiler.options.output.path;
        // 绑定钩子事件
        const hooks = compiler.hooks;
        hooks.done.tap('clean-webpack-plugin', stats => {
            console.log('done~')
        });
    }

}

引入自定义plugin

这个就很简单了,像平时引入plugin那样引入就OK了

// 引入插件
const {  CleanWebpackPlugin } = require('./clean-webpack-plugin');
module.exports = {
  plugins: [
   // 实例化构造函数
    new CleanWebpackPlugin(),
  ]
}

最后

感谢大家阅读,如有问题欢迎纠正!