0
点赞
收藏
分享

微信扫一扫

webpack原理篇(五十三):Tapable插件架构与Hooks设计


说明

玩转 webpack 学习笔记

compiler

上一节里面有个重要的东西就是 compiler

webpack原理篇(五十三):Tapable插件架构与Hooks设计_webpack

下面找一下这个东东,在 ​​my-project\node_modules\webpack\lib\webpack.js​​ 里面可以看到

webpack原理篇(五十三):Tapable插件架构与Hooks设计_ico_02


这里的 Compiler 跟 MultiCompiler 分别引用了不同的 js

const Compiler = require("./Compiler");
const MultiCompiler = require("./MultiCompiler");

找到 ​​my-project\node_modules\webpack\lib\Compiler.js​

webpack原理篇(五十三):Tapable插件架构与Hooks设计_ico_03


可以看到 Compiler 继承了 Tapable

webpack原理篇(五十三):Tapable插件架构与Hooks设计_类方法_04

Webpack 的本质

Webpack 可以将其理解是一种基于事件流的编程范例,一系列的插件运行。

核心对象 Compiler 继承 Tapable:

class Compiler extends Tapable {
// ...
}

核心对象 Compilation 继承 Tapable

class Compilation extends Tapable {
// ...
}

webpack原理篇(五十三):Tapable插件架构与Hooks设计_webpack_05

Tapable 是什么?

Tapable 是一个类似于 Node.js 的 EventEmitter 的库, 主要是控制钩子函数的发布与订阅,控制着 webpack 的插件系统。

Tapable 库暴露了很多 Hook(钩子)类,为插件提供挂载的钩子

const {
SyncHook, // 同步钩子
SyncBailHook, // 同步熔断钩子(遇到 return 直接返回)
SyncWaterfallHook, // 同步流水钩子(结果可以传递给下一个插件)
SyncLoopHook, // 同步循环钩子
AsyncParallelHook, // 异步并发钩子
AsyncParallelBailHook, // 异步并发熔断钩子
AsyncSeriesHook, // 异步串行钩子
AsyncSeriesBailHook, // 异步串行熔断钩子
AsyncSeriesWaterfallHook // 异步串行流水钩子
} = require("tapable");

Tapable hooks 类型

type

function

Hook

所有钩子的后缀

Waterfall

同步方法,但是它会传值给下一个函数

Bail

熔断:当函数有任何返回值,就会在当前执行函数停止

Loop

监听函数返回true表示继续循环,返回undefine表示结束循环

Sync

同步方法

AsyncSeries

异步串行钩子

AsyncParallel

异步并行执行钩子

Tapable 的使用:new Hook 新建钩子

Tapable 暴露出来的都是类方法,new 一个类方法获得我们需要的钩子

class 接受数组参数 options ,非必传。类方法会根据传参,接受同样数量的参数。

const hook1 = new SyncHook(["arg1", "arg2", "arg3"]);

Tapable 的使用:钩子的绑定与执行

Tabpack 提供了同步 ​​&​​ 异步绑定钩子的方法,并且他们都有绑定事件和执行事件对应的方法。

Async*

Sync*

绑定: ​​tapAsync/tapPromise/tap​

绑定: tap

执行: ​​callAsync/promise​

执行: call

Tapable 的使用:hook 基本用法示例

const hook1 = new SyncHook(["arg1", "arg2", "arg3"]);
// 绑定事件到webapck事件流
hook1.tap('hook1', (arg1, arg2,) => console.log(arg1, arg2, arg3)) //1,2,3
// 执行绑定的事件
hook1.call(1,2,3)

Tapable 的使用:实际例子演示

新建项目

1、我们先新建一个项目 ​​tapable-kaimo​​,然后执行下面命令

npm init -y
npm

webpack原理篇(五十三):Tapable插件架构与Hooks设计_ico_06

先添加一个 index.js 文件,输入下面代码

const {
SyncHook
} = require('tapable');

const hook = new SyncHook(["arg1", "arg2", "arg3"]);

hook.tap("hook1", (arg1, arg2,) => {
console.log(arg1, arg2, arg3);
});

hook.call(1, 2, 3);

运行 ​​node index.js​​ 结果如下

webpack原理篇(五十三):Tapable插件架构与Hooks设计_同步方法_07

实现下面例子

定义一个 Car 方法,在内部 hooks 上新建钩子。分别是同步钩子 accelerate、brake( accelerate 接受一个参数)、异步钩子 calculateRoutes。

使用钩子对应的绑定和执行方法

calculateRoutes 使用 tapPromise 可以返回一个 promise 对象

新建一个 car.js 文件,添加下面代码

const {
SyncHook,
AsyncSeriesHook
} = require('tapable');

// 创建 Car 类
class Car {
constructor() {
this.hooks = {
accelerate: new SyncHook(['newSpeed']), // 加速 hook
brake: new SyncHook(), // 刹车 hook
calculateRoutes: new AsyncSeriesHook(['source', 'target', 'routesList']) // 计算路径 hook
}
}
}

// 实例化 Car
const kaimoCar = new Car();

// 绑定同步钩子
kaimoCar.hooks.brake.tap('WarningLampPlugin', () => {
console.log('WarningLampPlugin');
})

// 绑定同步钩子 并传参
kaimoCar.hooks.accelerate.tap('LoggerPlugin', newSpeed => {
console.log(`Accelerate to ${newSpeed}`);
})

// 绑定一个异步 Promise 钩子
kaimoCar.hooks.calculateRoutes.tapPromise('calculateRoutes tapPromise', (source, target, routesList,) => {
return new Promise((resolve,) => {
setTimeout(() => {
console.log(`tapPromise to ${source} ${target} ${routesList}`);
resolve()
}, 1000)
})
})

/*****************下面开始执行***************/

kaimoCar.hooks.brake.call();
kaimoCar.hooks.accelerate.call(313);

console.time('kaimoCar cost');

kaimoCar.hooks.calculateRoutes.promise('Async', 'hook', 'kaimo demo').then(() => {
console.timeEnd('kaimoCar cost');
}, err => {
console.error(err);
console.timeEnd('kaimoCar cost');
})

运行命令执行 ​​node car.js​​,结果如下

webpack原理篇(五十三):Tapable插件架构与Hooks设计_同步方法_08


举报

相关推荐

0 条评论