tapable

Webpack本质上是一种事件流的机制,它的工作流程就是将各个插件串联起来,而实现这一切的核心就是Tapable,webpack中最核心的负责编译的Compiler和负责创建bundle的Compilation都是Tapable的实例

  1. const {
  2. SyncHook,
  3. SyncBailHook,
  4. SyncWaterfallHook,
  5. SyncLoopHook,
  6. AsyncParallelHook,
  7. AsyncParallelBailHook,
  8. AsyncSeriesHook,
  9. AsyncSeriesBailHook,
  10. AsyncSeriesWaterfallHook
  11. } = require("tapable");

SyncHook

串行同步执行,不关心返回值

  1. //钩子可以在stage和其他钩子之间穿插钩子
  2. const hook = new SyncHook()
  3. const calls = [];
  4. hook.tap("A",() => calls.push("A"))
  5. hook.tap({
  6. name:"B",
  7. before:"A"
  8. },() => calls.push("B"))
  9. calls.length = 0
  10. hook.call()
  11. hook.tap({
  12. name:"C",
  13. before:["A","B"]
  14. },() => calls.push("C"))
  15. calls.length = 0
  16. hook.call()
  17. hook.tap({
  18. name:"D",
  19. before:"B"
  20. },() => calls.push("D"))
  21. calls.length = 0;
  22. hook.call()
  23. hook.tap({
  24. name:"E",
  25. stage:3
  26. },() => calls.push("E"))
  27. hook.tap({
  28. name:"F",
  29. stage:1
  30. },() => calls.push("F"))
  31. calls.length = 0;
  32. hook.call()
  33. console.log(calls)
  34. //创建同步钩子
  35. const h0 = new SyncHook(["arg1"]);
  36. h0.tap("A",(name) => {
  37. console.log(name)
  38. })
  39. h0.tap("B",(name) => {
  40. console.log(name)
  41. })
  42. h0.call('plus',24)

SyncBailHook

串行同步执行,有一个返回值不为null则跳过剩下的逻辑

  1. const h1 = new SyncBailHook(["a"]);
  2. h1.tap("A",a => {console.log(a) ;return a})
  3. h1.tap("B",a => console.log(a))
  4. h1.call(1)

SyncWaterfallHook

  1. const h1 = new SyncWaterfallHook(['name'])
  2. h1.tap("A",(name) => {
  3. console.log(name,1)
  4. })
  5. h1.tap("B",(data) => {
  6. console.log(data,2)
  7. return 2
  8. })
  9. h1.tap("C",(data) => {
  10. console.log(data,3)
  11. return 3
  12. })
  13. h1.call('plus',24)

SyncLoopHook

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

  1. const h1 = new SyncLoopHook(['name'])
  2. let count = 0
  3. h1.tap('A',name => (
  4. count < 3 ?
  5. (count++,console.log(name),true)
  6. :undefined
  7. ))
  8. h1.call(
  9. 'plus'
  10. )

AsyncParallelHook

异步并行钩子

  1. const h1 = new AsyncParallelHook(['name'])
  2. h1.tap('A',() => console.log(1))
  3. h1.tap('B',() => console.log(2))
  4. h1.tap('C',() => console.log(3))
  5. h1.callAsync('test',err => {
  6. console.log(err)
  7. })
  1. const h1 = new AsyncParallelHook(['name'])
  2. console.time('count')
  3. h1.tapAsync('A',(name,callback) => {
  4. setTimeout(() => (console.log(1),callback()),2000)
  5. })
  6. h1.tapAsync('B',(name,callback) => {
  7. setTimeout(() => (console.log(2),callback()),1000)
  8. })
  9. h1.tapAsync('C',(name,callback) => {
  10. setTimeout(() => (console.log(3),callback()),3000)
  11. })
  12. h1.callAsync('test',err => {
  13. console.log(err)
  14. console.timeEnd('count')
  15. })
  1. const h1 = new AsyncParallelHook(['name'])
  2. console.time('count')
  3. h1.tapPromise('A',(name,callback) => (
  4. new Promise((resolve,reject) => {
  5. setTimeout(() => (console.log(1),resolve()),2000)
  6. })
  7. ))
  8. h1.tapPromise('B',(name,callback) => (
  9. new Promise((resolve,reject) => {
  10. setTimeout(() => (console.log(2),resolve()),1000)
  11. })
  12. ))
  13. h1.tapPromise('C',(name,callback) => (
  14. new Promise((resolve,reject) => {
  15. setTimeout(() => (console.log(3),resolve()),3000)
  16. })
  17. ))
  18. h1.callAsync('test',err => {
  19. console.log(err)
  20. console.timeEnd('count')
  21. })

AsyncParallelBailHook

带保险带异步执行钩子

  1. let h1=new AsyncParallelBailHook(['name']);
  2. console.time('count');
  3. h1.tap('A',function(name){
  4. console.log(1);
  5. return "Wrong";
  6. });
  7. h1.tap('B',function(name){
  8. console.log(2);
  9. });
  10. h1.tap('C',function(name){
  11. console.log(3);
  12. });
  13. h1.callAsync('test',err=>{
  14. console.log(err);
  15. console.timeEnd('count');
  16. });
  1. let h1=new AsyncParallelBailHook(['name']);
  2. console.time('count');
  3. h1.tapAsync('A',function(name,callback){
  4. console.log(1);
  5. return "Wrong";
  6. });
  7. h1.tapAsync('B',function(name,callback){
  8. console.log(2);
  9. });
  10. h1.tapAsync('C',function(name.callback){
  11. console.log(3);
  12. });
  13. h1.callAsync('test',err=>{
  14. console.log(err);
  15. console.timeEnd('count');
  16. });
  1. const h1 = new AsyncParallelBailHook(['name'])
  2. console.time('count')
  3. h1.tapPromise('A',(name,callback) => (
  4. new Promise((resolve,reject) => {
  5. setTimeout(() => (console.log(1),resolve()),2000)
  6. })
  7. ))
  8. h1.tapPromise('B',(name,callback) => (
  9. new Promise((resolve,reject) => {
  10. setTimeout(() => (console.log(2),resolve()),1000)
  11. })
  12. ))
  13. h1.tapPromise('C',(name,callback) => (
  14. new Promise((resolve,reject) => {
  15. setTimeout(() => (console.log(3),resolve()),3000)
  16. })
  17. ))
  18. h1.callAsync('test',err => {
  19. console.log(err)
  20. console.timeEnd('count')
  21. })

AsyncSeriesHook

异步串行钩子

  1. let h1 = new AsyncSeriesHook(['name']);
  2. console.time('cost');
  3. h1.tap('A',function(name){
  4. console.log(1);
  5. });
  6. h1.tap('B',function(name){
  7. console.log(2);
  8. });
  9. h1.tap('C',function(name){
  10. console.log(3);
  11. });
  12. h1.callAsync('test',err=>{
  13. console.log(err);
  14. console.timeEnd('cost');
  15. });
  1. let h1 = new AsyncSeriesHook(['name']);
  2. console.time('cost');
  3. h1.tapAsync('A',function(name,callback){
  4. setTimeout(function(){
  5. console.log(1);
  6. callback()
  7. },1000)
  8. });
  9. h1.tapAsync('B',function(name,callback){
  10. setTimeout(function(){
  11. console.log(2);
  12. callback()
  13. },2000)
  14. });
  15. h1.tapAsync('C',function(name,callback){
  16. setTimeout(function(){
  17. console.log(3);
  18. callback()
  19. },3000)
  20. });
  21. h1.callAsync('test',err=>{
  22. console.log(err);
  23. console.timeEnd('cost');
  24. });
  1. let h1=new AsyncSeriesHook(['name']);
  2. console.time('cost');
  3. h1.tapPromise('A',function(name){
  4. return new Promise(function(resolve){
  5. setTimeout(function(){
  6. console.log(1);
  7. resolve();
  8. },1000)
  9. });
  10. });
  11. h1.tapPromise('B',function(name,callback){
  12. return new Promise(function(resolve){
  13. setTimeout(function(){
  14. console.log(2);
  15. resolve();
  16. },2000)
  17. });
  18. });
  19. h1.tapPromise('C',function(name,callback){
  20. return new Promise(function(resolve){
  21. setTimeout(function(){
  22. console.log(3);
  23. resolve();
  24. },3000)
  25. });
  26. });
  27. h1.promise('test').then(data=>{
  28. console.log(data);
  29. console.timeEnd('cost');
  30. });

AsyncSeriesBailHook

  1. let h1 = new AsyncSeriesBailHook(['name']);
  2. console.time('cost');
  3. h1.tap('A',function(name){
  4. console.log(1);
  5. return "Wrong";
  6. });
  7. h1.tap('B',function(name){
  8. console.log(2);
  9. });
  10. h1.tap('C',function(name){
  11. console.log(3);
  12. });
  13. h1.callAsync('test',err=>{
  14. console.log(err);
  15. console.timeEnd('cost');
  16. });
  1. let h1 = new AsyncSeriesBailHook(['name']);
  2. console.time('cost');
  3. h1.tapAsync('A',function(name,callback){
  4. setTimeout(function(){
  5. console.log(1);
  6. callback('wrong')
  7. },1000)
  8. });
  9. h1.tapAsync('B',function(name,callback){
  10. setTimeout(function(){
  11. console.log(2);
  12. callback()
  13. },2000)
  14. });
  15. h1.tapAsync('C',function(name,callback){
  16. setTimeout(function(){
  17. console.log(3);
  18. callback()
  19. },3000)
  20. });
  21. h1.callAsync('test',err=>{
  22. console.log(err);
  23. console.timeEnd('cost');
  24. });
  1. const h1 = new AsyncSeriesBailHook(['name'])
  2. console.time('count')
  3. h1.tapPromise('A',(name,callback) => (
  4. new Promise((resolve,reject) => {
  5. setTimeout(() => (console.log(1),reject()),2000)
  6. })
  7. ))
  8. h1.tapPromise('B',(name,callback) => (
  9. new Promise((resolve,reject) => {
  10. setTimeout(() => (console.log(2),resolve()),1000)
  11. })
  12. ))
  13. h1.tapPromise('C',(name,callback) => (
  14. new Promise((resolve,reject) => {
  15. setTimeout(() => (console.log(3),resolve()),3000)
  16. })
  17. ))
  18. h1.promise('test',err => {
  19. console.log(err)
  20. console.timeEnd('count')
  21. },err => {
  22. console.log(err);
  23. console.timeEnd('cost');
  24. })

AsyncSeriesWaterfallHook

  1. let {AsyncSeriesWaterfallHook} = require('tapable');
  2. let h1 = new AsyncSeriesWaterfallHook(['name']);
  3. console.time('cost');
  4. h1.tap('1',function(name,callback){
  5. console.log(1);
  6. });
  7. h1.tap('2',function(data){
  8. console.log(2,data);
  9. });
  10. h1.tap('3',function(data){
  11. console.log(3,data);
  12. });
  13. queue.callAsync('test',err=>{
  14. console.log(err);
  15. console.timeEnd('cost');
  16. });
  1. let h1 = new AsyncSeriesWaterfallHook(['name']);
  2. console.time('cost');
  3. h1.tapAsync('1',function(name,callback){
  4. setTimeout(function(){
  5. console.log(1);
  6. callback(null,1);
  7. },1000)
  8. });
  9. h1.tapAsync('2',function(data,callback){
  10. setTimeout(function(){
  11. console.log(2);
  12. callback(null,2);
  13. },2000)
  14. });
  15. h1.tapAsync('3',function(data,callback){
  16. setTimeout(function(){
  17. console.log(3);
  18. callback(null,3);
  19. },3000)
  20. });
  21. h1.callAsync('test',(err,data)=>{
  22. console.log(err,data);
  23. console.timeEnd('cost');
  24. });
  1. let h1 = new AsyncSeriesWaterfallHook(['name']);
  2. console.time('cost');
  3. h1.tapPromise('1', function (name) {
  4. return new Promise(function (resolve) {
  5. setTimeout(function () {
  6. console.log(name, 1);
  7. resolve(1);
  8. }, 1000);
  9. });
  10. });
  11. h1.tapPromise('2', function (data) {
  12. return new Promise(function (resolve) {
  13. setTimeout(function () {
  14. console.log(data, 2);
  15. resolve(2);
  16. }, 2000);
  17. });
  18. });
  19. h1.tapPromise('3', function (data) {
  20. return new Promise(function (resolve) {
  21. setTimeout(function () {
  22. console.log(data, 3);
  23. resolve(3);
  24. }, 3000);
  25. });
  26. });
  27. h1.promise('test').then(err => {
  28. console.timeEnd('cost');
  29. });

tapable

  1. class MyPlugin {
  2. constructor(){
  3. this.hooks = {
  4. add:new SyncHook(['name'])
  5. }
  6. }
  7. }
  8. const myPlugin = new MyPlugin()
  9. myPlugin.hooks.add.tap('add',(name) => {
  10. console.log(name)
  11. })
  12. myPlugin.hooks.add.tap('minus',(name) => {
  13. console.log(name)
  14. })
  15. myPlugin.hooks.add.call('plus')

tapable事件流插件的更多相关文章

  1. .26-浅析webpack源码之事件流make(1)

    compilation事件流中,依然只是针对细节步骤做事件流注入,代码流程如图: // apply => this-compilation // apply => compilation ...

  2. .15-浅析webpack源码之WebpackOptionsApply模块-plugin事件流总览

    总体过了一下后面的流程,发现Compiler模块确实不适合单独讲解,这里继续讲解后面的代码: compiler.options = new WebpackOptionsApply().process( ...

  3. .21-浅析webpack源码之事件流this-compilation

    上一节生成Compilation实例后,添加了一些属性,随后触发this-compilation事件流,如下: Compiler.prototype.newCompilation = (params) ...

  4. .29-浅析webpack源码之doResolve事件流(1)

    在上一节中,最后返回了一个resolver,本质上就是一个Resolver对象: resolver = new Resolver(fileSystem); 这个对象的构造函数非常简单,只是简单的继承了 ...

  5. Wookmark-jQuery-master 瀑布流插件

    Wookmark-jQuery-master 瀑布流插件使用介绍,含个人测试DEMO 要求 必备知识 本文要求基本了解 Html/CSS,  JavaScript/JQuery. 开发环境 Dream ...

  6. .31-浅析webpack源码之doResolve事件流(2)

    放个流程图: 这里也放一下request对象内容,这节完事后如下(把vue-cli的package.json也复制过来了): /* { context: { issuer: '', compiler: ...

  7. .30-浅析webpack源码之doResolve事件流(1)

    这里所有的插件都对应着一个小功能,画个图整理下目前流程: 上节是从ParsePlugin中出来,对'./input.js'入口文件的路径做了处理,返回如下: ParsePlugin.prototype ...

  8. .27-浅析webpack源码之事件流make(2)

    上一节跑到了NormalModuleFactory模块,调用了原型方法create后,依次触发了before-rsolve.factory.resolver事件流,这节从resolver事件流开始讲. ...

  9. .25-浅析webpack源码之事件流compilation(3)

    这一节跑下一批plugin. compiler.apply( new EnsureChunkConditionsPlugin(), new RemoveParentModulesPlugin(), n ...

随机推荐

  1. CSS的nth-of-type和nth-child的区别

    <!--源代码--><!DOCTYPE html> <html lang="en"> <head> <meta charset ...

  2. ElasticSearch 因为磁盘空间不够引起的数据插入错误。(message [ClusterBlockException[blocked by: [FORBIDDEN/12/index read-only / allow delete (api)];]])

    ES升级到624测试从Kettle插入数据的时候,经常提示如下错误 message [ClusterBlockException[blocked by: [FORBIDDEN/12/index rea ...

  3. python全栈开发学习_day1_计算机五大组成部分及操作系统

    一.计算机五大组成部分: 1)五大组成: 1.控制器(指挥系统,用于控制其他计算机硬件的工作) 2.运算器(用于数学运算及逻辑运算) 3.存储器(寄存器,高速缓存,内存,磁盘(机械,固态),磁带) 4 ...

  4. django 中的聚合和分组 F查询 Q查询 事务cookies和sessions 066

    1 聚合和分组 聚合:对一些数据进行整理分析 进而得到结果(mysql中的聚合函数) 1aggregate(*args,**kwargs) : 通过对QuerySet进行计算 ,返回一个聚合值的字典. ...

  5. 在线词云制作tagxedo

    最近在用python制作词云的时候发现了一个更加方便快捷很好玩的词云制作网站 http://www.tagxedo.com/app.html 所以今天就来大致介绍下是怎么使用的 1.先来介绍下tagx ...

  6. 推荐 IntelliJ IDEA 牛逼的插件

    1. activate-power-mode 和 Power mode II 根据Atom的插件activate-power-mode的效果移植到IDEA上 写代码是整个屏幕都在抖动,activate ...

  7. 2016424王启元 Exp3免杀原理与实现

    基础问题回答 1.杀软是如何检测出恶意代码的? (1)基于特征码的检测 特征码是能识别一个程序是一个病毒的一段不大于64字节的特征串.如果一个可执行文件包含这样的特征码则被杀毒软件检测为是恶意代码. ...

  8. input获得焦点时改变placeholder文本的样式

    HTML: <input type="text" placeholder="sample text"/> CSS: input::-webkit-i ...

  9. Python数据类型(数字)

    文章内容参考了教程:http://www.runoob.com/python/python-basic-syntax.html#commentform Python 变量类型 变量存储在内存中的值.这 ...

  10. selenium+JDBC实现参数自动化测试

    测试模拟环境:在www.1905.com网站中执行两个用户的登陆退出操作 需要的文件有: 1.User的实例类: public class User { private String username ...