banner
banner
banner
NEWS LETTER

webpack --- 第三篇Tapable

Scroll down

了解webpack Plugin之前应该掌握Tapable
在 Webpack 的编译过程中,本质上通过 Tapable 实现了在编译过程中的一种『发布订阅者模式』的插件 Plugin 机制。

Tapable提供了一系列事件的发布订阅者API,通过Tapable使用者可以注册事件,从而在不同实际去触发注册的事件进行执行

官方提供的九种钩子

  • SyncHook
  • SyncBailHook
  • SyncWaterfallHook
  • SyncLoopHook
  • AsyncParallelHook
  • AsyncParallelBaiHook
  • AsyncSeriesHook
  • AsyncSeriesBailHook
  • AsyncSeriesWaterfallHook

Tapable中所有注册的事件可以分为同步、异步两种执行方式

  • 同步(Sync前缀): 表示注册的事件函数会同步进行执行
  • 异步(Async前缀): 表示注册的事件函数会异步进行执行
  • 异步串行钩子(AsyncSeries):可以被串联(连续按照顺序调用)执行的异步钩子函数
  • 异步并行钩子(AsyncParalle):可以被并联(并发调用)执行的异步钩子函数
  • 『同步钩子』唯一的注册事件方法:『tap』,执行调用『call』方法
  • 『异步钩子』
    • 注册方法:『tap、tapAsync、tapPromise』
    • 触发注册的方法:『call、callAsync、promise』一一对应

Tapable 按照执行机制分类

  • Basic Hook:基本类型钩子,仅执行钩子注册的事件,不关心被调用事件的返回值
  • Waterfall:瀑布类型的钩子,会在注册事件执行时将事件函数执行非undefined的返回值传递给接下来的事件函数作为参数,其他的与基本类型钩子类似
  • Bail:保险类型钩子,在基础类型钩子上增加一个保险机制,『任意一个注册函数执行返回非undefined的值,整个钩子执行过程会立即中断』,之后的注册事件就不会调用
  • Loop: 循环类型钩子,通过 call 调用时,『任意一个注册的事件返回值非 undefeind则立即重头开始重新执行所有的注册事件,直到所有被注册的事件函数都返回 undefined』
  • 注册事件: 通过tap函数监听对应的事件,接受两个参数:参数一仅作标识, 参数二在调用时会执行
    1
    hook.tap(String|Object, 本次注册的函数)
  • 调用事件: 通过call方法传入对应的参数,调用注册在hook内部的事件函数执行,同时将call方法传入的参数传递给每一个注册的事件函数作为『实参』
  • 示例
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    const {SyncHook, SyncBailHook, SyncWaterfallHook,SyncWaterfallHook } = require('tapable')
    const hook = new SyncHook(['arg1','arg2','arg3']) // 这个就换钩子名,其他一样
    // SyncHook注册与调用事件
    // 初始化同步钩子
    重点:数组中对应的字符串个数
    hook.tap('flag1',(arg1,arg2,arg3) => {})
    hook.call('1','2','3')

    // SyncBailHook注册与调用事件
    hook.tap('flag1',(arg1,arg2,arg3) =>{
    // 存在返回值,阻断后面注册事件的调用
    return true
    })
    hook.call('1','2','3')
  • 参考:Tapable讲解

拦截器

  • Tapable 提供的所有 Hook 都支持注入 Interception ,可以通过拦截器对整个Tapable发布/订阅流程进行监听
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    hook.intercept({
    // 每次通过 tap、tapAsync、tapPromise 方法注册事件函数时,会触发 register 拦截器。
    // 并且接受 tap 作为参数, 还可以对注册事件进行修改;
    register: (tapInfo) => {
    console.log(`${tapInfo.name} is doing its job`);
    return tapInfo
    },
    // 通过hook实例对象上的call方法时候触发拦截器,接受的参数为调用 Hook 时传入的参数。
    call: (arg1, arg2, arg3) => {},
    // 在调用被注册的每一个事件函数之前执行,接受参数为对应的 Tap 对象。
    tap: (tap) => {},
    // loop类型钩子中 每次重新开始 loop 之前会执行该拦截器,拦截器函数接受的参数为调用时传入的参数。
    loop: (...args) => {},
    });

API

Before && stage

  • before 值类型为Array | String,值为注册事件对象时的名称,它可以让当前事件在对应标识事件前执行』
  • stage 值类型为Number,『数字越大事件回调执行的越晚』,支持传入负数,默认为0
  • 使用:在注册事件函数,第一个参数为对象时,在这个对象添加stage和before来控制本次注册事件的执行时机
  • 如果同时使用 before 和 stage 时,会优先处理 before ,在满足 before 的条件之后才会进行 stage 的判断。不建议同时使用
    1
    2
    3
    4
    5
    6
    7
    8
    hook.tap({
    name: 'flag1'
    },()=>{})
    hook.tap({
    name:'flag2',
    // flag2 会在flag1前执行
    before:'flag1'
    },()=> {})

HookMap

  • 辅助类,管理Hook
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    // 创建HookMap实例
    const keyedHook = new HookMap((key) => new SyncHook(['arg']));
    // 在keyedHook中创建一个name为key1的hook,同时为该hook通过tap注册事件
    keyedHook.for('key1').tap('Plugin 1', (arg) => {
    console.log('Plugin 1', arg);
    });
    // 从HookMap中拿到name为key1的hook
    const hook = keyedHook.get('key1');
    if (hook) {
    // 通过call方法触发Hook
    hook.call('hello');
    }
其他文章
cover
webpack --- 第四篇
  • 24/11/01
  • 16:52
  • 前端工程化工具
cover
webpack --- 第二篇
  • 24/11/01
  • 16:52
  • 前端工程化工具
目录导航 置顶
  1. 1. 官方提供的九种钩子
  2. 2. Tapable中所有注册的事件可以分为同步、异步两种执行方式
  3. 3. Tapable 按照执行机制分类
  4. 4. 拦截器
  5. 5. API
请输入关键词进行搜索