Tapable 基本用法介绍

147 阅读2分钟

Tapable:实现发布订阅的一个库。在 Webpack 中广泛使用。

Github:Tapble

注:文章中使用的 version 为 2.2.1

README 介绍:The tapable package expose many Hook classes, which can be used to create hooks for plugins.

这个库暴露了各种类型的 Hook 的类,让我们使用。

1. SyncHook

最简单的一个同步 Hook:顺序执行 tap 进去的函数( tapped function )。

举个 🌰:从上到下 tap 了三个函数,执行的顺序也是按照 tap 的顺序。

/**
 * @author: lxdll
 * Tapable: SyncHook
 */
 
const { SyncHook } = require('tapable')

// 实例化 SyncHook
const syncHook = new SyncHook(['arg'])

// function1 -> tap
syncHook.tap('function1', (arg) => {
  console.log('function1 arg: ', arg)
  console.log('function1 call.')
  console.log('---------------')
})

// function2 -> tap
syncHook.tap('function2', (arg) => {
  console.log('function2 arg: ', arg)
  console.log('function2 call.')
  console.log('---------------')
})

// function3 -> tap
syncHook.tap('function3', (arg) => {
  console.log('function3 arg: ', arg)
  console.log('function3 call.')
  console.log('---------------')
})

// SyncHook 调用
syncHook.call('I am arg.')

运行结果:

image.png

2. SyncBailHook

可以 提前终止 的同步 Hook:当有一个任意的 tapped function 返回了 non-undefined 的值,那么 SyncBailHook 会停止执行剩下的 tapped function。

Bail 效果,个人理解就是一个熔断的效果,即提前终止整个 call 的过程。

举个 🌰:在 function2 中,我们 return 了一个值,会触发 Bail 效果,导致不会触发 function2 后面的 function3。

/**
 * @author: lxdll
 * Tapable: SyncBailHook
 */

const { SyncBailHook } = require('tapable')

// 实例化 SyncBailHook
const syncBailHook = new SyncBailHook(['arg'])

// function1 -> tap
syncBailHook.tap('function1', (arg) => {
  console.log('function1 arg: ', arg)
  console.log('function1 call.')
  console.log('---------------')
})
 
// function2 -> tap
syncBailHook.tap('function2', (arg) => {
  console.log('function2 arg: ', arg)
  console.log('function2 call.')
  console.log('---------------')

  return 'anything'
})
 
// function3 -> tap
syncBailHook.tap('function3', (arg) => {
  console.log('function3 arg: ', arg)
  console.log('function3 call.')
  console.log('---------------')
})

// SyncBailHook 调用
syncBailHook.call('I am arg.')

运行结果:

image.png

注:直接写 return; / return undefined; 都不会触发 Bail 效果。

3. SyncLoopHook

可循环执行的同步 Hook:在顺序执行 tapped function 过程中,如果有任意一个 tapped function 返回了 non-undefined 的值,那么 SyncLoopHook 会 restart,从第一个 tapped function 重新开始执行,直到所有的 tapped function 都没有返回 non-undefined 的值。

举个 🌰:我们初始化时有一个 tappedFunction2Flag 为 false,在执行到 function2 时,我们触发 restart,并且将 flag 置为 true。

/**
 * @author: lxdll
 * Tapable: SyncLoopHook
 */

const { SyncLoopHook } = require('tapable')

// function2 的标识
let tappedFunction2Flag = false

// 实例化 SyncLoopHook
const syncLoopHook = new SyncLoopHook(['arg'])
 
// function1 -> tap
syncLoopHook.tap('function1', (arg) => {
  console.log('function1 arg: ', arg)
  console.log('function1 call.')
  console.log('---------------')
})
  
// function2 -> tap
syncLoopHook.tap('function2', (arg) => {
  console.log('function2 arg: ', arg)
  console.log('function2 call.')
  console.log('---------------')

  // 第一次执行过来时,触发 Loop
  // 并且将 flag 置为 true,之后就不会触发 Loop 了
  if (!tappedFunction2Flag) {
    tappedFunction2Flag = true
    console.log('restart && loop.')
    return 'non-undefined'
  }
})
  
// function3 -> tap
syncLoopHook.tap('function3', (arg) => {
  console.log('function3 arg: ', arg)
  console.log('function3 call.')
  console.log('---------------')
})
 
syncLoopHook.call('I am arg.')

运行结果:

image.png

4. SyncWaterfallHook

瀑布型同步 Hook:顺序执行 tapped function 时,当前执行的 tapped function 的入参是上一个 tapped function 的返回值。

注:如果恰好上一个 tapped function 没有返回值,那么取上上个的返回值。

/**
 * @author: lxdll
 * Tapable: SyncWaterfallHook
 */

const { SyncWaterfallHook } = require('tapable')
 
// 实例化 SyncWaterfallHook
const syncWaterfallHook = new SyncWaterfallHook(['arg'])
  
// function1 -> tap
syncWaterfallHook.tap('function1', (arg) => {
  console.log('function1 arg: ', arg)
  console.log('function1 call.')
  console.log('---------------')

  return 'function1 result.'
})
   
// function2 -> tap
syncWaterfallHook.tap('function2', (arg) => {
  console.log('function2 arg: ', arg)
  console.log('function2 call.')
  console.log('---------------')

  return 'function2 result.'
})
   
// function3 -> tap
syncWaterfallHook.tap('function3', (arg) => {
  console.log('function3 arg: ', arg)
  console.log('function3 call.')
  console.log('---------------')

  return 'function3 result.'
})
 
syncWaterfallHook.call('Init arg.')

运行结果:

image.png

5. AsyncSeriesHook

6. AsyncSeriesBailHook

7. AsyncSeriesLoopHook

8. AsyncSeriesWaterfallHook

9. AsyncParallelHook

10. AsyncParallelBailHook