• webpack源码分析——tapable


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

    一、tapable用途

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

    二、tapable中的apply方法

    apply方法的源码:

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

    一个插件的简单实现大致如下所示:

    实际的例子如下:

    var compiler = new Complier();

    compiler.apply(new SimplePlugin());

    三、实现事件机制的其他API

     tapable中其他的API都是为实现事件机制准备。webpack中的事件机制正是通过tapable实现的。需要进行事件处理的类通过继承tapable类拥有事件处理的能力。下面我们先看看tapable中是如何实现事件机制的。

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

    触发事件的方法:applyPlugins、applyPlugins0、applyPlugins1、applyPlugins2;applyPluginsWaterfall、applyPluginsWaterfall0、applyPluginsWaterfall1、applyPluginsWaterfall2;applyPluginsBailResult、applyPluginsBailResult1、applyPluginsBailResult2、applyPluginsBailResult3、applyPluginsBailResult4、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、applyPlugins1、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、applyPlugins1、applyPlugins2用法与applyPlugins类似,只是监听函数对应的参数不同而已。applyPlugins0对应的监听函数没有参数;applyPlugins1对应的监听函数有一个参数;applyPlugins2对应的监听函数有两个参数。

    3.1.2 applyPluginsWaterfall、applyPluginsWaterfall0、applyPluginsWaterfall1、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、applyPluginsBailResult1、applyPluginsBailResult2、applyPluginsBailResult3、applyPluginsBailResult4、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、applyPlugins1、applyPlugins2;applyPluginsWaterfall、applyPluginsWaterfall0、applyPluginsWaterfall1、applyPluginsWaterfall2;applyPluginsBailResult、applyPluginsBailResult1、applyPluginsBailResult2、applyPluginsBailResult3、applyPluginsBailResult4、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(){})

  • 相关阅读:
    开发时需要安装的插件
    update svn cache 慢
    eclipse cut copy paste plugin
    eclipse怎么自定义工具栏
    Eclipse Class Decompiler——Java反编译插件(转)
    2014年下半年软考系统架构设计师考试试题
    IT痴汉的工作现状36-做好准备再上路
    JSP简单练习-EL获取表单数据
    !HDU 1078 FatMouse and Cheese-dp-(记忆化搜索)
    iOS百度地图
  • 原文地址:https://www.cnblogs.com/xiaokebb/p/8418905.html
Copyright © 2020-2023  润新知