jerryni / blog

:dog: :dog: :dog:
https://github.com/jerryni/blog/issues
11 stars 4 forks source link

Webpack4.0源码之Tapable模块 #34

Open jerryni opened 4 years ago

jerryni commented 4 years ago

webpack本质上是一种事件流的机制,它的工作流程就是将各个插件串联起来,而实现这一切的核心就是Tapable,webpack中最核心的负责编译的Compiler和负责创建bundles的Compilation都是Tapable的实例。本文主要介绍一下Tapable中的钩子函数。

// hello world start //////////////////////////////////
const { SyncHook } = require('tapable');
let queue = new SyncHook(['name']);

*// 1 x1 undefined*
queue.tap('1', (name, name2) => {
  console.log('1', name, name2);
  return '1';
})

*// 2 x1 undefined*
queue.tap('2', (name, name2) => {
  console.log('2', name, name2);
  return '2';
})

*// 为什么x2这个参数无效? 因为参数和 new实例的时候一致*
queue.call('x1', 'x2');
// hello world end //////////////////////////////////
// 简单理解: 其实就是发布订阅模式,tap(sub)订阅,call(pub)发布

// 原理代码
class SyncHook_MY{
    constructor(){
        this.hooks = [];
    }

    // 订阅
    tap(name, fn){
        this.hooks.push(fn);
    }

    // 发布
    call(){
        this.hooks.forEach(hook => hook(...arguments));
    }
}

// 这个模块里暴露了这些函数:
const {
    SyncHook,
    SyncBailHook,
    SyncWaterfallHook,
    SyncLoopHook,
    AsyncParallelHook,
    AsyncParallelBailHook,
    AsyncSeriesHook,
    AsyncSeriesBailHook,
    AsyncSeriesWaterfallHook
 } = require("tapable");

// 这些函数统一接收 “字符串数组” 为参数
const hook = new SyncHook(["arg1", "arg2", "arg3"]);

常用的钩子主要包含以下几种,分为同步和异步,异步又分为并发执行和串行执行,如下图: img1

其他函数的说明如下: img2

怎么在webpack里查看勾子是什么类型?

在源码中,可以找到具体的类型,如图 image

参考资料: 原文 - 中文翻译