webpack源码分析——tapable

Webpack的整个流程是经过tapable的事件流机制串联起来。理解tapable对于阅读源代码的做用极大。本文分析的Tapable源码的版本是0.2.7。webpack

1、tapable用途

tapable中大量的API主要是为了实现两个功能,一个做用是经过apply方法在complier中注册插件;另外一个做用就是实现事件机制。web

2、tapable中的apply方法

apply方法的源码:app

源码意思很明显,就是调用传入对象的apply方法。在webpack中,这个传入的对象就是插件的实例对象。异步

一个插件的简单实现大体以下所示:函数

实际的例子以下:spa

var compiler = new Complier();插件

compiler.apply(new SimplePlugin());3d

3、实现事件机制的其余API

 tapable中其余的API都是为实现事件机制准备。webpack中的事件机制正是经过tapable实现的。须要进行事件处理的类经过继承tapable类拥有事件处理的能力。下面咱们先看看tapable中是如何实现事件机制的。对象

所谓的事件处理,就是触发事件和监听事件blog

触发事件的方法:applyPlugins、applyPlugins0、applyPlugins一、applyPlugins2;applyPluginsWaterfall、applyPluginsWaterfall0、applyPluginsWaterfall一、applyPluginsWaterfall2;applyPluginsBailResult、applyPluginsBailResult一、applyPluginsBailResult二、applyPluginsBailResult三、applyPluginsBailResult四、applyPluginsBailResult5;applyPluginsAsyncSeries、applyPluginsAsync、applyPluginsAsyncSeries1;applyPluginsAsyncSeriesBailResult、applyPluginsAsyncSeriesBailResult1;applyPluginsAsyncWaterfall;applyPluginsParallel;applyPluginsParallelBailResult、applyPluginsParallelBailResult1。

监听事件的方法:plugin

webpack中实现事件机制大概分为三步:

第一步、须要实例化Tapable类或者实例化继承自tapable的类

var tapable = new Tapable();

第二步、监听特定的事件(至关于JS中的addEventListerner)

tapable.plugin("test", function(a,b,callback){
    console.log('函数1:'+a+b);
    callback();
});

第三步、触发特定的事件(至关于trigger方法)

tapable.applyPluginsAsync("test", '123','qeeqeq', function(){

    console.log('cb4');
});

tapable中监听事件的方法就只有一个plugin方法,触发事件的方法有applyPlugins、applyPluginsWaterfall等等,下面详细介绍一下这些触发事件的方法。

3.1 触发事件的分类及详细说明

3.1.1 applyPlugins、applyPlugins0、applyPlugins一、applyPlugins2方法

 applyPlugins方法使用说明:

用法:

var tapable = new Tapable();

tapable.applyPlugins('eventname', param1, param2, ...... paramn),

tapable.plugin('eventname', function(param1, param2,...... paramn){})

applyPlugins0使用说明:

源码:

用法:

var tapable = new Tapable();

tapable.applyPlugins0('eventname');

tapable.plugin('eventname', funtion(){});

applyPlugins1的使用说明:

源码:

用法:

var tapable = new Tapable();

tapable.applyPlugins0('eventname', param1);

tapable.plugin('eventname', funtion(param1){});

applyPlugins2的使用说明:

源码:

用法:

var tapable = new Tapable();

tapable.applyPlugins0('eventname', param1, param2);

tapable.plugin('eventname', funtion(param1, param2){});

小结:applyPlugins0、applyPlugins一、applyPlugins2用法与applyPlugins相似,只是监听函数对应的参数不一样而已。applyPlugins0对应的监听函数没有参数;applyPlugins1对应的监听函数有一个参数;applyPlugins2对应的监听函数有两个参数。

3.1.2 applyPluginsWaterfall、applyPluginsWaterfall0、applyPluginsWaterfall一、applyPluginsWaterfall2

这组方法的意思是触发某个特定的事件,这个特定的事件会被一系列的流程监听。每一个流程处理完后,将结果做为参数传递给下一个监听函数继续处理,直至全部的监听函数执行完毕。最终触发事件的函数获取全部监听函数处理的结果。

 applyPluginsWaterfall使用说明:

源码:

用法:

 var tapable = new Tapable();

 tapable.plugin('eventname', function(processValue, param1, param2,......, paramn){});

 tapable.plugin('eventname', function(processValue, param1, param2,......, paramn){});

 var result = tapable.applyPluginsWaterfall('eventname', defaultValue, param1, param2,......paramn);

applyPluginsWaterfall0使用说明:

源码:

 

用法:

var tapable = new Tapable();

 tapable.plugin('eventname', function(processValue){});

 tapable.plugin('eventname', function(processValue){});

 var result = tapable.applyPluginsWaterfall('eventname', defaultValue);

applyPluginsWaterfall1使用说明:

源码:

 

用法:

 var tapable = new Tapable();

 tapable.plugin('eventname', function(processValue, param1){});

 tapable.plugin('eventname', function(processValue, param1){});

 var result = tapable.applyPluginsWaterfall('eventname', defaultValue, param1);

applyPluginsWaterfall2使用说明:

源码:

 

用法:

 var tapable = new Tapable();

 tapable.plugin('eventname', function(processValue, param1, param2){});

 tapable.plugin('eventname', function(processValue, param1, param2){});

 var result = tapable.applyPluginsWaterfall('eventname', defaultValue, param1, param2);

小结:applyPluginsWaterfall系列触发的事件在参数中须要传入默认值(须要被加工的数据),在监听函数处理完后,须要获取默认值被处理完后的结果。

3.1.3 applyPluginsBailResult、applyPluginsBailResult一、applyPluginsBailResult二、applyPluginsBailResult三、applyPluginsBailResult四、applyPluginsBailResult5

 这个系列的触发函数须要有返回值,它还有一个特殊之处在监听函数有返回值的状况下,会提早返回。仅以applyPluginsBailResult为例,其余几个方法只是参数不一样而已。

源码:

用法:

 

小结:从执行结果能够看出第二个监听函数返回告终果后,第三次监听就没有执行。最终的返回结果是第二次监听的结果。

3.1.4 applyPluginsAsyncSeries、applyPluginsAsync、applyPluginsAsyncSeries1

仅以applyPluginsAsync为例进行分析

 源码:

用法:

 

小结:从源码和执行结果上看,这组方法的做用是模仿异步的工做流程,在一个监听执行完后,在这个监听的回调函数里面去执行下一个监听函数,相似异步流程。

3.1.5 applyPluginsAsyncSeriesBailResult、applyPluginsAsyncSeriesBailResult1

 以applyPluginsAsyncSeriesBailResult为例进行分析

源码:

用法:

 

从源码和执行结果上分析,applyPluginsAsyncSeriesBailResult函数时以异步的方式进行调用监听函数,但能够提早返回(监听函数的回调函数中有参数)。

3.1.6 applyPluginsAsyncWaterfall

 源码:

用法:

 

小结:applyPluginsAsyncWaterfall方法是以异步的方式串联起监听函数,每一个监听函数将前一个函数的处理结果做为参数继续处理,监听函数的整个执行过程就像流水线同样运做。

3.1.7 applyPluginsParallel

 源码:

用法:

 

小结:从源码和运行结果来看,applyPluginsParallel方法触发的方法是并行执行的,三个监听函数最后调用的callback函数(这个callback指的是触发函数执行的回调)与代码的编写顺序无关,与实际结束的时间相关。三个监听函数,最后执行的才会调用触发函数中的回调函数。

3.1.8 applyPluginsParallelBailResult、applyPluginsParallelBailResult1

源码:

用法:

小结:从源码和执行结果分析,applyPluginsParallelBailResult触发的方法是并行执行,与applyPluginsParallel不一样的是,触发函数的回调能够提早执行(没必要等全部的监听函数执行完毕)。

 总结

apply方法用来注册插件。

plugin用来监听具体事件。

applyPlugins、applyPlugins0、applyPlugins一、applyPlugins2;applyPluginsWaterfall、applyPluginsWaterfall0、applyPluginsWaterfall一、applyPluginsWaterfall2;applyPluginsBailResult、applyPluginsBailResult一、applyPluginsBailResult二、applyPluginsBailResult三、applyPluginsBailResult四、applyPluginsBailResult5;applyPluginsAsyncSeries、applyPluginsAsync、applyPluginsAsyncSeries1;applyPluginsAsyncSeriesBailResult、applyPluginsAsyncSeriesBailResult1;applyPluginsAsyncWaterfall;applyPluginsParallel;applyPluginsParallelBailResult、applyPluginsParallelBailResult1 这些方法用来触发具体事件

触发函数的区别以下表所示:

方法名 监听函数的回调函数的最后一个参数是不是函数 监听函数执行方式 触发函数是否有返回值 触发函数的参数中是否有回调函数 触发函数的回调函数可否提早执行
applyPlugins 不涉及 不涉及
applyPluginsWaterfall 不涉及 不涉及
applyPluginsBailResult 不涉及 不涉及
applyPluginsAsyncSeries 异步 监听函数正常执行不会提早执行
applyPluginsAsyncSeriesBailResult 异步 能够
applyPluginsAsyncWaterfall 异步 监听函数正常执行不会提早执行
applyPluginsParallel 同步 监听函数正常执行不会提早执行
applyPluginsParallelBailResult 同步 能够

说明:

监听函数指的是:plugin函数

监听函数的回调函数指的是(标红的函数):plugin('eventname', callbackfn())

触发函数指的是:applyPlugins等函数

触发函数的回调函数指的是(标红的函数):tapable.applyPluginsAsync('eventname', params, function(){})

相关文章
相关标签/搜索