这是我参与8月更文挑战的第7天,活动详情查看:8月更文挑战webpack
Webpack 本质上是一种事件流的机制,它的工做流程就是将各个插件串联起来,而实现这一切的核心就是 tapable
,Webpack 中最核心的,负责编译的 Compiler
和负责建立 bundles
的 Compilation
都是 tapable
构造函数的实例。git
Tapable就是webpack用来建立钩子
的库
。 Tapable
是webpack内部使用的一个流程管理工具,主要用来串联插件,完善事件流执行。github
简单来讲,Tapable
就是webpack用来建立钩子
的,那么为何webapck要建立钩子呢?咱们先看下面一句话:web
webpack的核心功能是经过抽离出不少
插件
来实现的。能够说插件就是webpack的基石,这些基石又影响着流程的走向。这些钩子是经过Tapable
串起来的,能够类比Vue框架的生命周期,webpack也有本身的生命周期,在周期里边会顺序地触发一些钩子,挂载在这些钩子上的插件的方法
得以执行,从而进行一些特定的逻辑处理。在插件里边,构建的实体或构建出来的数据结果都是可触达的,这样作实现了webpack的高度可扩展。promise
咱们先简单理解一下插件,插件
就是功能的扩展,不会影响原有的数据。markdown
在webpack整个运行流程中,咱们须要不少插件放在特定的时期去扩展咱们想要的功能。插件是如何实现本身代码的功能呢?就是经过在webpack的各类钩子
函数上挂载
本身的方法
。webapck运行时会本身执行
钩子上挂载的这些插件的方法。因此,webapck须要在运行的各个时期暴露
出钩子
,好让插件在这些钩子上挂载他们要执行的方法。webapck的钩子都是经过Tapable
建立的。框架
咱们能够把webpack实例理解为一个长的衣柜
,从上到下表明着webpack运行期间不一样的流程。webpack从上到下建立了不一样时期的衣架(钩子),有挂鞋的,挂衣服的,挂裤子的,那么咱们就能够在这些钩子上挂载咱们想要挂载的东西(插件的各类方法)。异步
Tapable 中主要提供了同步
与异步
两种钩子。async
同步钩子:函数
SyncHook,
SyncBailHook,
SyncWaterfallHook,
SyncLoopHook,
复制代码
异步钩子:
异步并行钩子:
AsyncParallelHook,
AsyncParallelBailHook,
复制代码
异步串行钩子:
AsyncSeriesHook,
AsyncSeriesBailHook,
AsyncSeriesWaterfallHook,
复制代码
同步钩子的使用:
SyncHook,
SyncBailHook,
SyncWaterfallHook,
SyncLoopHook,
复制代码
SyncHook:
// 同步钩子
const {
SyncHook,
SyncBailHook,
SyncWaterfallHook,
SyncLoopHook,
} = require ('tapable');
// 初始化hook,肯定参数
const syncHK = new SyncHook(['name', 'age'])
// 生产商品,注册事件
syncHK.tap( 'plugin1', (name, age)=> {
console.log('plugin1:', name, age);
} )
syncHK.tap('plugin2:', (name, age) => {
console.log('plugin2:', name, age);
})
// 消费
syncHK.call('zack', 18)
复制代码
SyncBailHook:
const bailHook = new SyncBailHook(['name', 'age'])
// 注册事件
bailHook.tap('a', (name, age) => {
console.log('a:', name, age);
})
bailHook.tap('b', (name, age) => {
console.log('b:', name, age);
return 'b'
})
bailHook.tap('c', (name, age) => {
console.log('c:', name, age);
})
// 消费
bailHook.call('lili', 20)
// result2
// a: lili 20
// b: lili 20
复制代码
SyncWaterfallHook:
const waterFallHK = new SyncWaterfallHook(['name', 'age'])
// 注册事件
waterFallHK.tap('one', (name, age) => {
console.log('one:', name, age);
return age
})
waterFallHK.tap('two', (age) => {
console.log('two:', age);
})
// 消费
waterFallHK.call('pilipili', 25)
// result3
// one: pilipili 25
// two: 25
复制代码
SyncLoopHook:
let num = 20
const loopHK = new SyncLoopHook (['name', 'age'])
// 生产商品
loopHK.tap('1', (name, age) => {
console.log('1:', name, age);
if(num>18) {
num--;
console.log('num:', num);
return num
}
})
loopHK.tap('2', (name, age) => {
console.log('2', name, age);
})
// 消费
loopHK.call('kiki', 21)
// result4:
// 1: kiki 21
// num: 19
// 1: kiki 21
// num: 18
// 1: kiki 21
// 2 kiki 21
复制代码
异步并行钩子的使用:
异步钩子注册通常不使用tap,否则最后仍是会串行,使用后两种。
全部任务一块儿执行,谁先完成谁先输出,全部任务执行完后执行回调。
AsyncParallelHook,
AsyncParallelBailHook,
复制代码
AsyncParallelHook:
异步并行执行,当全部注册事件都执行完成后,才执行callAsync
或者promise
。
const asyncPHK = new AsyncParallelHook(['name'])
asyncPHK.tapAsync('print1', (name, callbackName) => {
setTimeout(() => {
console.log('1', name);
callbackName('hhhh', '11')
}, 2000)
})
asyncPHK.callAsync('lili', (err, res) => {
console.log('err', err);
console.log('res', res);
})
// 1 lili
// err hhhh
// res undefined
复制代码
const asyncPHK2 = new AsyncParallelHook(['name'])
asyncPHK2.tapPromise('1', (name) => {
// tapPromise须要返回一个Promise
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log(name, 1);
resolve('11')
}, 2000)
})
})
asyncPHK2.tapPromise('2', (name) => {
// tapPromise须要返回一个Promise
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log(name, 2);
resolve('22')
}, 1000)
})
})
// 触发
asyncPHK2.promise('tapPromise')
.then(res => {
console.log('over', res);
})
.catch(err => {
console.log('error', err);
})
// tapPromise 2
// tapPromise 1
// over undefined
复制代码
AsyncParallelBailHook:
const asyncPBailHK = new AsyncParallelBailHook(['name'])
asyncPBailHK.tapAsync('1', (name, callBK) => {
setTimeout(() => {
console.log(name, 01);
callBK('001')
}, 2000)
})
asyncPBailHK.tapAsync('2', (name, callBK) => {
setTimeout(() => {
console.log(name, 02);
callBK('002')
}, 1000)
})
asyncPBailHK.callAsync('bail', (res) => {
console.log(res);
})
// bail 2
// bail 1
// 001
复制代码
const asyncPBailHK2 = new AsyncParallelBailHook(['name'])
asyncPBailHK2.tapPromise('2', (name) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log(name, 22);
resolve('222')
}, 2000)
})
})
asyncPBailHK2.tapPromise('2', (name) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log(name, 23);
resolve('223')
}, 1000)
})
})
asyncPBailHK2.promise('bail222')
.then(res => {
console.log('over', res);
})
.catch(err => {
console.log('err', err);
})
复制代码
异步串行钩子的使用:
AsyncSeriesHook,
AsyncSeriesBailHook,
AsyncSeriesWaterfallHook,
与上相同。