webpack自定义plugin

416 阅读2分钟

1.plugin自定义

webpack在编译代码过程中 ⽣命周期概念 对应不同的打包阶段

不同打包阶段

  • module
  • Assets plugin本质上是⼀个类

它是如何注册到webpack的对应阶段的

2.webpack的打包流程

  1. 拿到配置,初始化⼯作 最终配置
  2. 实例化⼀个compiler类,注册插件,对应的⽣命周期绑定相应的时间
  3. 执⾏编译,compiler.run //各阶段
  4. compiler(构建阶段)->compilation(第七个阶段,bundle资源被加⼯成什么样⼦了)
  5. 递归处理所有的依赖模块 ⽣成chunk
  6. 把chunk输出到output指定的位置

3.生命周期钩子

//示例1
const pluginName = 'ConsoleLogOnBuildWebpackPlugin';
//compiler hook 的 tap 方法的第一个参数,应该是驼峰式命名的插件名称。建议为此使用一个常量,以便它可以在所有 hook 中复用。
class ConsoleLogOnBuildWebpackPlugin {
  apply(compiler) {
    compiler.hooks.run.tap(pluginName, compilation => {
      console.log('webpack 构建过程开始!');
    });
  }
} 

//示例2 触发所有hooks 对应的自定义事件test
const webpack = require("webpack");
const webpackConfig = require("./webpack.config.js");

const compiler = webpack(webpackConfig);
Object.keys(compiler.hooks).forEach((hookName) => {//拿到所有钩子的名字
  compiler.hooks[hookName].tap("test", () => {//添加对应的tap事件,test为定义的事件名,可以多次订阅
    console.log(`run ------ > ${hookName}`);
  });
});

compiler.run();//运行webpack

// run ------ > beforeRun
// run ------ > run
// run ------ > normalModuleFactory
// run ------ > contextModuleFactory
// run ------ > beforeCompile 
// ...
// run ------ > compile
// run ------ > thisCompilation
// run ------ > compilation
// run ------ > make
// run ------ > normalModuleFactory
// run ------ > contextModu 
// run ------ > assetEmitted
// run ------ > assetEmitted
// run ------ > afterEmit
// run ------ > done

compiler.hooks[hookName].tap的实现,订阅发布

class SyncHook {
        construct
            or(options) {
        this.options = options
        this.hooks = []  //存放监听函数的数组
    } 
    tap(name, callback) {
       this.hooks.push(callback)
    }
    call(...args) {
        for (let i = 0; i < this.hooks.length; i++) {
            this.hooks[i](...args)
        }
   }
}
 
const synchook = new SyncHook('name')
// 注册监听函数
synchook.tap('name', (data) => {
     console.log('name', data)
})
synchook.tap('age', (data) => {
    console.log('age', data)
})
 
//发布事件
synchook.call('test')

4.自定义打包文本plugin

//myPlugins/txt-webpack-plugin.js
class TxtWebpackPlugin {
  // apply函数 帮助插件注册,接收complier类
  constructor(options) {
    console.log(options);
  }
  apply(complier) {
  //这是一个异步的钩子
    complier.hooks.emit.tapAsync("TxtWebpackPlugin", (compilation, cb) => {
      //   console.log(compilation.assets);
      compilation.assets["xxx.txt"] = {
        source: function () {
          // 定义文件的内容
          return "输出内容XXXXXXXX!!!!!";
        },
        size: function () {
          // 定义文件的体积
          return 1024;
        },
      };
      cb();//记得要调用回调cb才能往下进入下一个钩子
    });
     //这是一个同步的钩子
    complier.hooks.compile.tap("TxtWebpackPlugin", (compilation) => {
      console.log("哈哈 我是一个同步的钩子");
    });
  }
}
module.exports = TxtWebpackPlugin;

//webpack.config.js

const txtWebpackPlugin = require("./myPlugins/txt-webpack-plugin.js");

module.exports = {
...
  plugins: [
    new txtWebpackPlugin({
      name: "参数11",
    }),
  ...
  ]
}