【重学webpack系列——webpack5.0】

以下是本节正文:


  • tapable 是一个类似于 Node.js 中的 EventEmitter的库,但更专注于自定义事件的触发和处理
  • webpack本质上是一种事件流的机制,它的工作流程就是将各个插件串联起来,而实现这一切的核心就是Tapable。Tapable其实就是一个用于事件发布订阅执行的插件架构。webpack 通过 tapable 将实现与流程解耦,所有具体实现通过插件的形式存在。
  • tapable核心原理:发布订阅模式。

1.tapable的使用

tapable在webpack中被广泛应用,先来看看tapable是怎么使用的吧~

let { SyncHook }  = require("tapable");
let syncHook = new SyncHook();

syncHook.tap("name1", (...args) => { // 监听,类似events的on
  console.log('name1', ...args)
})
syncHook.tap("name2", (...args) => {
  console.log("name2", ...args);
})
syncHook.tap("name2", (...args) => {
  console.log("name22", ...args);
})

syncHook.call("name2", 'a', 'b'); // 触发
/*
	结果为
	name1
    name2
    name22
*/
  • 可见tapable这个库,监听用tap,触发用call,且上面无论是箭头还是触发的第一个参数,也就是name,是没有任何意义的

2.手写tapable

module.exports = class SyncHook {
  constructor(){
    this.events = []
  }
  tap(eventName, callback){
    this.events.push(callback);
  }
  call(eventName, ...args){
    this.events.forEach(fn => fn(...args))
  }
}

3.优化tapable

优化tapable,使得其能指定触发某一个事件

module.exports = class SyncHook {
  constructor(){
    this.events = {}
  }
  tap(eventName, callback){
    if (this.events[eventName]) {
      this.events[eventName].push(callback)
    } else {
      this.events[eventName] = [callback];
    }
  }
  call(eventName, ...args){
    if (eventName && this.events[eventName]) {
      this.events[eventName].forEach(fn => fn());
    } else if (!eventName) {
      Object.keys(this.events).forEach(e => {
        this.events[e].forEach(fn => fn(...args))
      })
    }
  }
}

4.关于tapable的钩子函数

可以参照以下链接:

25、tapable(1)——介绍_俞华的博客-CSDN博客

26、tapable(2)——SyncHook_俞华的博客-CSDN博客

27、tapable(3)——SyncBailHook_俞华的博客-CSDN博客

28、tapable(4)——SyncWaterfallHook_俞华的博客-CSDN博客

29、tapable(5)——SyncLoopHook_俞华的博客-CSDN博客