webpack2源码责任链模式

90 阅读1分钟

责任链模式

责任链是一种行为设计模式,可让您沿着处理程序链传递请求。收到请求后,每个处理程序决定处理请求,然后将其传递给链中的下一个处理程序。

webpack责任链模式

normalModuleFactory创建normalModule实例过程中有说到normalResolver解析资源路径的过程。normalResolver会涉及下面这些插件,每个插件都有各自的功能,实际上就是责任划分,通过一个链将各个责任进行连接。

340985655-a619d349-278c-45a7-9e44-1ff454997ccf.png 在node_modules/enhanced-resolve/lib/ResolverFactory.js实例化一系列插件,实例化插件如下:

340982434-06312804-0f1a-4098-8088-9a26e0679e81.png 看到每个插件都有source和target属性,source是指定插件的监听事件名称,target就是用来确定下一步的去向事件。

340985526-3d1a546c-6a2a-46e4-9e2c-eaeb19c13b8e.png 通过resolver.apply(plugin)注册监听插件事件,监听事件如下图所示:

340982609-8411978f-10f9-44f0-9b86-ba00c1e8a133.png

下面我们看下代码实现:

//node_modules/enhanced-resolve/lib/ParsePlugin.js
function ParsePlugin(source, target) {
	this.source = source;
	this.target = target;
}
module.exports = ParsePlugin;

ParsePlugin.prototype.apply = function(resolver) {
	var target = this.target;
	resolver.plugin(this.source, function(request, callback) {
		var parsed = resolver.parse(request.request);
		var obj = Object.assign({}, request, parsed);
		if(request.query && !parsed.query) {
			obj.query = request.query;
		}
		if(parsed && callback.log) {
			if(parsed.module)
				callback.log("Parsed request is a module");
			if(parsed.directory)
				callback.log("Parsed request is a directory");
		}
		resolver.doResolve(target, obj, null, callback);
	});
};


plugins.push(new ParsePlugin("resolve", "parsed-resolve"));
plugins.push(new DescriptionFilePlugin("parsed-resolve", descriptionFiles, "described-resolve"));
doResolve(type, request, message, callback) {
  if(resolver.hasPlugins(type)) {
    resolver.applyPluginsAsyncSeriesBailResult1(type, request, createInnerCallback(innerCallback, {
      log: callback.log,
      missing: callback.missing,
      stack: newStack
    }, message));
  }
}

new ParsePlugin("resolve", "parsed-resolve")指定source为"resolve",target为"parsed-resolve" 。即ParsePlugin监听事件为"resolve",执行完resolve相关操作后,触发执行parsed-resolve事件。parsed-resolve事件在DescriptionFilePlugin插件注册监听,DescriptionFilePlugin插件执行完parsed-resolve相关操作后,然后触发described-resolve事件。关键在于职责分离,而后存在链式调用以形成执行链。