plugin实现

使用Plugin

安装插件, 创建插件即可

new cleanWebpackPlugin();

综上所述得出一个结论: 插件是一个类

Plugin的特点

clean-webpack-plugin, 会在打包之前清空指定目录
html-webpack-plugin, 会在打包之后拷贝HTML文件并将打包好的文件插入到HTML中
综上所述得出一个结论: 插件可以在打包过程中的特定阶段执行

大型框架实现在特点阶段执行插件代码

Frame通过Tapable在不同的阶段发送了不同的通知,
我们只需要在编写插件时注册我们需要监听的通知即可

综上所述: 只要会编写类, 只要会使用Tapable订阅消息, 就会写插件
*(Tapabale的原理及使用可参考我的“实现发布订阅模式”文章)
(plugin就是订阅者,它向发布者(frame)在特定阶段订阅消息,frame在特定阶段发布消息(执行此plugin))

插件的基本格式

class CustomPlugin {
    constructor(options){
        console.log("插件被创建了", options);
    }
    apply(compiler){
        console.log("插件被执行了", options);
    }
}
module.exports = CustomPlugin;

传入的compiler对象中除了包含webpack打包的配置以外,
还包含了webpack各阶段消息发布者

例如:
entryOption: 给webpack编译器传递配置文件之后
run: webpack编译器run方法被执行
emit: 打包文件写入之前
afterEmit: 打包文件写入之后
done: 打包完成
… …

实例

我们为webpack写一个简单的插件(webpack-clean-plugin),主要功能是清除之前所创建的目录及文件,代码如下:

const path = require("path");
const fs = require("fs");

class CleanWebpackPlugin {
    constructor(options){
        console.log("插件被创建了", options);
    }
    apply(compiler){
        // 可以通过compiler对象的options拿到webpack的配置文件
        let outputPath = compiler.options.output.path;
        compiler.hooks.entryOption.tap("CleanWebpackPlugin", () => {
            this.cleanDir(outputPath);
        });
    }
    cleanDir(dirPath){
        // 注意点: 在NodeJS中不能直接删除非空的目录
        // 1.判断是否是一个非空的目录
        if(fs.statSync(dirPath).isDirectory() && fs.readdirSync(dirPath).length !== 0){
            // 2.如果是一个非空的目录, 那么就先删除这个目录中的内容
            let files = fs.readdirSync(dirPath);
            files.forEach((file)=>{
                let filePath = path.resolve(dirPath, file);
                if(fs.statSync(filePath).isDirectory()){
                    this.cleanDir(filePath);
                }else{
                    fs.unlinkSync(filePath);
                }
            })
        }
        // 3.如果不是一个非空的目录, 那么就直接删除这个目录
        fs.rmdirSync(dirPath);
    }
}
module.exports = CleanWebpackPlugin;

我们来看这句核心代码:

        compiler.hooks.entryOption.tap("CleanWebpackPlugin", () => {
            this.cleanDir(outputPath);
        });

plugin是订阅者,他向发布者(hooks,即webpack)订阅一个消息:在entryoption之后执行此plugin。

接下来我们便可以创建发布者发布消息。

安装tapable

npm install tapable

导入配置

const {
    SyncHook,
    SyncBailHook,
    SyncWaterfallHook,
    SyncLoopHook,
    AsyncParallelHook,
    AsyncParallelBailHook,
    AsyncSeriesHook,
    AsyncSeriesBailHook,
    AsyncSeriesWaterfallHook
} = require("tapable");

创建发布者

        this.hooks = {
            entryOption: new SyncBailHook(),
        }

获取插件, 调用插件的apply方法, 并且将当前的编译对象传递给插件

        let plugins = this.config.plugins;
        plugins.forEach((plugin) => {
            plugin.apply(this);
        });

在entryOption阶段发布(传递完配置文件后 )

cp.hooks.entryOption.call();

总结
1.创建订阅者,即编写plugin(向发布者指定在哪个阶段执行)

2.创建发布者,获取plugin的信息并传入配置

3.在某个阶段发布(即执行plugin)

至此,plugin的原理和实现完成。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值