webpack底层工具库tapable基本使用

tapable工作流程

  • 实例化hook注册事件监听
  • 通过hook触发事件监听
  • 执行懒编译生成的可执行代码
【webpack底层工具库tapable基本使用】Hook本职是tapable实例对象,分同步和异步,异步分并行和串行两种模式
Hook执行特点
Hook:普通钩子,监听器之间互相独立不干扰
BailHook:熔断钩子,某个监听返回非undefined时后续不执行
WaterfallHoook: 瀑布钩子,上一个监听的返回值可传递至下一个
LoopHook:循环钩子,如果当前未返回false则一直执行
tapable库同步钩子:SynckHook,SyncBailHoook,SyncWaterfallHook,SyncLoopHook
异步串行钩子:AsyncSeriesHoook,AsyncSeriesBailHook,AsyncSeriesWaterfallHook,异步并行钩子:AsyncParallerHook,AsyncParalleBailHook
同步钩子: SyncHook
let { SyncHook, SyncBailHook } = require('tapable')// 创建钩子 let hook = new SyncHook(['name', 'age'])hook.tap('fn1', function (name, age) { console.log('fn1', name, age) })hook.tap('fn2', function (name, age) { console.log('fn2', name, age) })hook.tap('fn3', function (name, age) { console.log('fn3', name, age) })hook.call('jack', 18)

webpack底层工具库tapable基本使用
文章图片

结果都能因此打印
SyncBailHook
let bailHook = new SyncBailHook(['name', 'age']) bailHook.tap('fn1', function (name, age) { console.log('fn1', name, age) }) bailHook.tap('fn2', function (name, age) { console.log('fn2', name, age) return 'tom' // fn1,fn2,会打印,fn3不会打印 // return undefined // fn1,fn2,fn3都会打印 })bailHook.tap('fn3', function (name, age) { console.log('fn3', name, age) })bailHook.call('jack', 18)

webpack底层工具库tapable基本使用
文章图片

如果返回非undefined,流程就会终止
SyncWaterfallHook
let waterfallhook = new SyncWaterfallHook(['name', 'age'])waterfallhook.tap('fn1', function (name, age) { console.log('fn1', name, age) return 'fn1' })waterfallhook.tap('fn2', function (name, age) { console.log('fn2', name, age) return 'fn2' })waterfallhook.tap('fn3', function (name, age) { console.log('fn3', name, age) return 'fn3' })waterfallhook.call('jack', 18)

webpack底层工具库tapable基本使用
文章图片

SyncWaterfallHook可以通过return把返回值传递给下一个钩子
SyncLoopHook
let loophook = new SyncLoopHook(['name', 'age']) let cnt1 = 0 let cnt2 = 0 let cnt3 = 0loophook.tap('fn1', function (name, age) { console.log('fn1', name, age) if (++cnt1 === 2) { cnt1 === 0 return undefined } return true })loophook.tap('fn2', function (name, age) { console.log('fn2', name, age) })loophook.tap('fn3', function (name, age) { console.log('fn3', name, age) })loophook.call('jack', 18)

webpack底层工具库tapable基本使用
文章图片

tap函数体内设置了判断条件,如果不满足条件,SyncLoopHook会重头开始继续执行
异步钩子 对于异步钩子的使用,在添加事件监听时会存在三种方式:taptapAsynctapPromise
异步并行钩子:AsyncParallerHook
tap方式监听
let hook = new AsyncParallelHook(['name'])hook.tap('fn1', function (name) { console.log('fn1', name) }) hook.tap('fn2', function (name) { console.log('fn2', name) }) hook.callAsync('jack', function () { console.log('operate async') })

webpack底层工具库tapable基本使用
文章图片

tapAsync方式监听
console.time('time') hook.tapAsync('fn1', function (name, callback) { setTimeout(() => { console.log('fn1', name) callback() }, 1000); }) hook.tapAsync('fn2', function (name, callback) { setTimeout(() => { console.log('fn2', name) callback() }, 2000); }) hook.callAsync('jack', function () { console.log('operate tapAsync') console.timeEnd('time') })

webpack底层工具库tapable基本使用
文章图片

从执行结果来看,是并行执行
tapPromise方式监听
console.time('time') hook.tapPromise('fn1', function (name) { return new Promise(function (resolve, reject) { setTimeout(() => { console.log('fn1', name) resolve() }, 1000); }) }) hook.tapPromise('fn2', function (name) { return new Promise(function (resolve, reject) { setTimeout(() => { console.log('fn2', name) resolve() }, 2000); }) }) hook.promise('jack').then(() => { console.log('end') console.timeEnd('time') })

webpack底层工具库tapable基本使用
文章图片

AsyncParallelBailHook
let hook = new AsyncParallelBailHook(['name']); console.time('time') hook.tapAsync('fn1', function (name, callback) { setTimeout(() => { console.log('fn1', name) callback() }, 1000); }) hook.tapAsync('fn2', function (name, callback) { setTimeout(() => { console.log('fn2', name) callback('err') // 熔断操作 }, 2000); }) hook.tapAsync('fn3', function (name, callback) { setTimeout(() => { console.log('fn3', name) callback() }, 3000); }) hook.callAsync('jack', function () { console.log('end') console.timeEnd('time') })

webpack底层工具库tapable基本使用
文章图片

fn3最后是执行了,但是在fn2后就熔断了.
AsyncSeriesHook串行
let hook = new AsyncSeriesHook(['name']) console.time('time') hook.tapPromise('fn1', function (name) { return new Promise((resolve, reject) => { setTimeout(() => { console.log('fn1', name) resolve() }, 1000); }) }) hook.tapPromise('fn2', function (name) { return new Promise((resolve, reject) => { setTimeout(() => { console.log('fn2', name) resolve() }, 2000); }) }) hook.promise('fn').then(function () { console.log('end') console.timeEnd('time') })

webpack底层工具库tapable基本使用
文章图片

从结果来看,代码是串行执行

    推荐阅读