基于数据结构从源码解析webpack核心模块tapable

webpack作为前端打包的重要工具之一,我们有必要深入掌握webpack的底层数据结构。官方文档上直接给出了webpack的核心模块tapable,但是并没有给出特别详细的介绍其实现原理和内部实现,本文从源码触发,来解析下tapable的数据结构和方法属性,这对于掌握webpack打包机制的理解是很有帮助的。

总览:

hook.js数据结构:

  constructor(args) {
		if (!Array.isArray(args)) args = [];
		this._args = args;
		this.taps = [];
		this.interceptors = [];
		this.call = this._call;
		this.promise = this._promise;
		this.callAsync = this._callAsync;
		this._x = undefined;
	}

两个集合,taps集合,interceptors集合,并定义了三个操作tap的方法tap, tapAsync, tapPromise,对应的还有三个创建委托函数(将监听函数转化为字符串)的方法_call, _promise, _callAsync

HookCodeFactory

各种钩子的工厂类基础类,每个钩子的工厂类会继承HookCodeFactory。比如syncHook

const Hook = require("./Hook");
const HookCodeFactory = require("./HookCodeFactory");

class SyncHookCodeFactory extends HookCodeFactory {
	content({ onError, onDone, rethrowIfPossible }) {
		return this.callTapsSeries({
			onError: (i, err) => onError(err),
			onDone,
			rethrowIfPossible
		});
	}
}

const factory = new SyncHookCodeFactory();

class SyncHook extends Hook {
	tapAsync() {
		throw new Error("tapAsync is not supported on a SyncHook");
	}

	tapPromise() {
		throw new Error("tapPromise is not supported on a SyncHook");
	}

	compile(options) {
		factory.setup(this, options);
		return factory.create(options);
	}
}

module.exports = SyncHook;

说明:各种钩子继承Hook类之后,会定义compile方法,该方法调用了工厂类实例,最终和HookCodeFactory联系起来,在各种钩子上去执行HookCodeFactory的方法

HookCodeFactory的方法:

主要实现了串行,并行,循环,执行单个监听函数的方法,也就是taps出栈的方法

HookMap的数据结构

  constructor(factory) {
		this._map = new Map();
		this._factory = factory;
		this._interceptors = [];
	}

可以看出,在hookMap内定义了字典的数据结构来存储hook实例

  for(key) {
		const hook = this.get(key);
		if (hook !== undefined) {
			return hook;
		}
		let newHook = this._factory(key);
		const interceptors = this._interceptors;
		for (let i = 0; i < interceptors.length; i++) {
			newHook = interceptors[i].factory(key, newHook);
		}
		this._map.set(key, newHook);
		return newHook;
	}

for方法将传入的factory的hook设置到字典

MultiHook

    constructor(hooks) {
		this.hooks = hooks;
	}

	tap(options, fn) {
		for (const hook of this.hooks) {
			hook.tap(options, fn);
		}
	}

	tapAsync(options, fn) {
		for (const hook of this.hooks) {
			hook.tapAsync(options, fn);
		}
	}

	tapPromise(options, fn) {
		for (const hook of this.hooks) {
			hook.tapPromise(options, fn);
		}
	}

批量操作hooks

其余钩子

其余的钩子函数都具有类似性,根据串行,并行或者其他在钩子工厂实例的content方法中执行不同的HookCodeFactory方法

比如:


 

总结:

同步钩子:

  • SyncBailHook:类似于 SyncHook,执行过程中注册的回调返回非 undefined 时就停止不在执行。
  • SyncWaterfallHook:接受至少一个参数,上一个注册的回调返回值会作为下一个注册的回调的参数。
  • SyncLoopHook:有点类似 SyncBailHook,但是是在执行过程中回调返回非 undefined 时继续再次执行当前的回调。

异步钩子与之相同,这里不再阐述具体实现原理。

图解钩子类型:
image

image

参考:https://segmentfault.com/a/1190000020146256

           https://www.cnblogs.com/Darlietoothpaste/p/10474871.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值