webpack Tapable

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

用法

All Hook constructors take one optional argument, which is a list of argument names as strings.

class Car {
	constructor() {
		this.hooks = {
			accelerate: new SyncHook(["newSpeed"]),
			brake: new SyncHook(),
			calculateRoutes: new AsyncParallelHook(["source", "target", "routesList"])
		}
	}
}

const muCar = new Car()
//注册监听
//同步钩子
myCar.hooks.accelerate.tap("LoggerPlugin", newSpeed => console.log(`Accelerating to ${newSpeed}`));
myCar.hooks.brake.tap("WarningLampPlugin", () => warningLamp.on());
//异步钩子
myCar.hooks.calculateRoutes.tapPromise("GoogleMapsPlugin", (source, target, routesList) => {
	return google.maps.findRoute(source, target).then(route => {
		routesList.add(route);
	});
});

钩子注册(钩入)方式

  1. 同步
    • tap
  2. 异步
    • tap
    • tapPromise
    • tapAsync

Hooks type

每个钩子都能监听一个或多个函数,函数如何执行取决于钩子的类型

  • hook 基础钩子
  • bail hook 只要有一个handler有返回值,剩下handler不执行
  • waterfall hook 上一个handler的返回值当做下一个handler的入参
  • loop hook 循环 只要钩子有返回值,不停loop
  • sync hook 同步
  • async hook 异步
  • Async series 异步串行
  • Async parallel 异步并行

拦截器

每个钩子都有拦截器,每个拦截器接收call,tap,register,loop,context五个属性

const {
	SyncLoopHook,
}  = require("../lib/index")

class Test {
	constructor(){
		this.hooks = {
			test: new SyncLoopHook(["name"]),
		};
	}
}

const objTest = new Test()
objTest.hooks.test.intercept({
  //当钩子使用call调用
	call: (name) => {
		console.log("call");
	},
  //当插件进入钩子的时候调用(注册),Tap对象无法更改
	tap: (Tap) => {
		console.log("tap");
	},
  //当钩子循环的时候调用
	loop: (name)=>{
		console.log('loop');
	},
  //钩子使用tap调用,并且可以修改Tap对象
	register: (Tap) => {
		console.log("register");
	},
});
objTest.hooks.test.tap('testPlugin',(name)=>{
	console.log(name);
})
objTest.hooks.test.call('test')

//输出结果如下
register
call
loop
tap
test

//Tap对象结构
interface Tap {
	name: string,
	type: string
	fn: Function,
	stage: number,
	context: boolean,
	before?: string | Array
}

webpack中如何使用Tapable

  1. hooks均继承自hook(lib/Hook.js)

  2. Tap tapAsync tappromise会把handler丢入到数组中。

  3. call callAsync promise会按照相应的顺序去执行数组中的handler

    //以SyncHook为例 精简版
    lass SyncHookCodeFactory extends HookCodeFactory {
    	content({ onError, onDone, rethrowIfPossible }) {
    		return this.callTapsSeries({
    			onError: (i, err) => onError(err),
    			onDone,
    			rethrowIfPossible
    		});
    	}
    }
    
    const factory = new SyncHookCodeFactory();
    const COMPILE = function(options) {
    	factory.setup(this, options);
    	return factory.create(options);
    };
    
    1. callcallAsyncpromise最终会调用每个hook的COMPILE方法

    2. COMPILE方法会实例化继承自HookCodeFactory的相应类并调用HookCodeFactory的create方法

      • create方法用new Function(‘a’,‘b’,‘return a+b’)方式去创建每个handler的执行函数字符串

        问:为啥用new Function去创建函数?

        答:函数入参和函数体会根据入参的长度而动态生成,这样你可以根据实际情况来控制传入参数的个数,并且函数也只处理这几个入参。

参考

  1. Tapable readme
  2. 掘金-雾豹-深入源码解析 tapable 实现原理
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值