webpack底层工具库tapable基本使用

tapable工作流程

  • 实例化hook注册事件监听
  • 通过hook触发事件监听
  • 执行懒编译生成的可执行代码

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)

image.png
结果都能因此打印

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)

image.png
如果返回非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)

image.png
SyncWaterfallHook可以通过return把返回值传递给下一个钩子

SyncLoopHook

let loophook = new SyncLoopHook(['name', 'age'])
let cnt1 = 0
let cnt2 = 0
let cnt3 = 0

loophook.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)

image.png
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')
})

image.png

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')
})

image.png
从执行结果来看,是并行执行

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')
})

image.png

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')
})

image.png
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')
})

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

你可能感兴趣的:(webpack4tapable)