热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Webpack源码(一)——Tapable和事宜流

1、TapableTap的英文单词诠释,除了最经常运用的点击手势以外,另有一个意义是水龙头——在webpack中指的是后一种;Webpack能够认为是一种基于事宜流的编程范例,内部

1、Tapable

Tap 的英文单词诠释,除了最经常运用的 点击 手势以外,另有一个意义是 水龙头 —— 在 webpack 中指的是后一种;

Webpack 能够认为是一种基于事宜流的编程范例,内部的事情流程都是基于 插件 机制串接起来;

而将这些插件粘合起来的就是webpack本身写的基础类 Tapable 是,plugin要领就是该类暴露出来的;

背面我们将看到中心的对象 Compiler、Compilation 等都是继承于该对象

基于该类范例而其的 Webpack 体系保证了插件的有序性,使得全部体系异常有弹性,扩展性很好;但是有一个致命的瑕玷就是调试、看源码真是很痛楚,种种跳来跳去;(基于事宜流的写法,和程序语言中的 goto 语句很类似)

把这个堆栈下载,运用 Webstorm 举行调试,test 目次是很好的教程进口;

Tapable.plugin():相称于把对象归类到名为 name 的对象下,以array的情势;一切的插件都存在私有变量 _plugin 变量中;

《Webpack 源码(一)—— Tapable 和 事宜流》

接下来我们简朴节选几个函数剖析一下:

1.1、apply 要领

该要领最一般也是最经常运用的,看一下它的定义:


Tapable.prototype.apply = function apply() {
for(var i = 0; i arguments[i].apply(this);
}
};

毫无牵挂,就是 挨个递次 实行传入到该函数要领中对象的 apply 要领;一般传入该函数的对象也是 Tapable 插件 对象,因而必定也存在 apply 要领;(Webpack 的插件就是Tapable对象,因而必需要供应 apply 要领 )

只是变动上下文为当前 this

因而当前这里最大的作用就是传入当前 Tapable 的上下文

1.2、 applyPluginsAsync(name,…other,callback)

// 模仿两个插件
var _plugins = {
"emit":[
function(a,b,cb){
setTimeout(()=>{
console.log('1',a,b);
cb();
},1000);
},
function(a,b,cb){
setTimeout(()=>{
console.log('2',a,b);
cb();
},500)
}
]
}
applyPluginsAsync("emit",'#a','bbbbb',function(){console.log('end')});
// 输出效果:
// 1 #a bbbbb
// 2 #a bbbbb
// end

我们看到,虽然第一个插件是延后 1000ms 实行,第二个则是延后 500ms,但在真正实行的时刻,是严厉根据递次实行的;每一个插件须要在末了显式挪用cb()关照下一个插件的运转;

这里须要注重每一个插件的形参的个数都要一致,且末了一个必需是cb()要领,用于唤起下一个插件的运转;cb的第一个参数是err,假如该参数不为空,就直接挪用末了callback,中缀后续插件的运转;

1.3、 applyPluginsParallel(name,…other,callback)

大部分代码和
applyPluginsAsync 有点儿类似

这个 applyPluginsParallel 主要功用和 最简朴的 applyPlugins 要领比较类似,无论怎样都邑让一切注册的插件运转一遍

只是比拟 applyPlugins 多了一个分外的功用,它末了 供应一个 callback 函数,这个 callback 的函数比较顽强,假如一切的插件x都一般实行,且末了都cb(),则会在末了实行callback里的逻辑;不过,一旦个中某个插件运转失足,就会挪用这个callback(err),以后就算插件有毛病也不会再挪用该callback函数;


var _plugins = {
"emit":[
function(a,b,cb){
setTimeout(()=>{
console.log('1',a,b);
cb(null,'e222','33333');
},1000);
},
function(a,b,cb){
setTimeout(()=>{
console.log('2',a,b);
cb(null,'err');
},500)
}
]
}
applyPluginsParallel("emit",'#a','bbbbb',function(a,b){console.log('end',a,b)});
// 输出效果:
// 2 #a bbbbb
// 1 #a bbbbb
// end undefined undefined

上面的两个插件都是挪用了 cb,且第一个参数是 null(示意没有毛病),所以末了能输出 callback 函数中的 console 内容;

假如解释两个插件中任何一个 cb() 挪用,你会发明末了的 callback 没有实行

假如让 第二个 cb()的第一个值不是 null,比方 cb(‘err’),则 callback 以后输出这个毛病,以后再也不会挪用此 callback:

var _plugins = {
"emit":[
function(a,b,cb){
setTimeout(()=>{
console.log('1',a,b);
cb('e222','33333');
},1000);
},
function(a,b,cb){
setTimeout(()=>{
console.log('2',a,b);
cb('err');
},500)
}
]
}
// 输出效果:
// 2 #a bbbbb
// end err undefined
// 1 #a bbbbb

1.4、 applyPluginsWaterfall(name, init, callback)

望文生义,这个要领相称因而 瀑布式 挪用,给第一个插件传入初始对象 init,然后经由第一个插件挪用以后会取得一个效果对象,该效果对象会传给下一个插件 作为初始值,直到末了挪用终了,末了一个插件的直接效果传给 callback 作为初始值;

1.5、 applyPluginsParallelBailResult(name,…other,callback)

这个要领应该是一切要领中最难明白的;

起首它的行动和 applyPluginsParallel 异常类似,起首会 无论怎样都邑让一切注册的插件运转一遍(根据注册的递次)

为了让 callback 实行,其前提条件是每一个插件都须要挪用 cb();

但个中的 callback 只会实行一次(当传给cb的值不是undefined/null 的时刻),这一次实行递次是插件定义递次有关,而跟每一个插件中的 cb() 实行时间无关的


var _plugins = {
"emit":[
function(a,b,cb){
setTimeout(()=>{
console.log('1',a,b);
cb();
},1000);
},
function(a,b,cb){
setTimeout(()=>{
console.log('2',a,b);
cb();
},500)
},
function(a,b,cb){
setTimeout(()=>{
console.log('3',a,b);
cb();
},1500)
}
]
}
applyPluginsParallelBailResult("emit",'#a','bbbbb',function(a,b){console.log('end',a,b)});
// 运转效果
// 2 #a bbbbb
// 1 #a bbbbb
// 3 #a bbbbb
// end undefined undefined

这是最一般的运转状况,我们轻微调解一下(注重三个插件运转的递次2-1-3),分别给cb传入有用的值:


var _plugins = {
"emit":[
function(a,b,cb){
setTimeout(()=>{
console.log('1',a,b);
cb('1');
},1000);
},
function(a,b,cb){
setTimeout(()=>{
console.log('2',a,b);
cb('2');
},500)
},
function(a,b,cb){
setTimeout(()=>{
console.log('3',a,b);
cb('3');
},1500)
}
]
}
applyPluginsParallelBailResult("emit",'#a','bbbbb',function(a,b){console.log('end',a,b)});
// 运转效果
// 2 #a bbbbb
// 1 #a bbbbb
// end 1 undefined
// 3 #a bbbbb

能够发明第1个插件 cb('1') 实行了,后续的 cb('2')cb('3') 都给疏忽了;

这是由于插件注册递次是 1-2-3,虽然运转的时刻递次是 2-1-3,但所运转的照样 1 对应的 cb;所以,就算1实行的速率最慢(比方把其setTimeout的值设置成 2000),运转的 cb 仍然是1对应的cb;

个中触及的魔法是
闭包,传入的
i就是和注册递次绑定了

如许一申明,你会发明 applyPluginsParallel 的 cb 实行机遇是和实行时间有关联的,你能够本身考证一下;

1.6、总结

总结一下,Tapable 就相称因而一个 事宜管家,它所供应的 plugin 要领类似于 addEventListen 监听事宜,apply 要领类似于事宜触发函数 trigger

《Webpack 源码(一)—— Tapable 和 事宜流》


推荐阅读
  • 1.如何在运行状态查看源代码?查看函数的源代码,我们通常会使用IDE来完成。比如在PyCharm中,你可以Ctrl+鼠标点击进入函数的源代码。那如果没有IDE呢?当我们想使用一个函 ... [详细]
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • 本文详细介绍了如何在Linux系统上安装和配置Smokeping,以实现对网络链路质量的实时监控。通过详细的步骤和必要的依赖包安装,确保用户能够顺利完成部署并优化其网络性能监控。 ... [详细]
  • 本文详细介绍了如何使用 Yii2 的 GridView 组件在列表页面实现数据的直接编辑功能。通过具体的代码示例和步骤,帮助开发者快速掌握这一实用技巧。 ... [详细]
  • golang常用库:配置文件解析库/管理工具viper使用
    golang常用库:配置文件解析库管理工具-viper使用-一、viper简介viper配置管理解析库,是由大神SteveFrancia开发,他在google领导着golang的 ... [详细]
  • 非公版RTX 3080显卡的革新与亮点
    本文深入探讨了图形显卡的进化历程,重点介绍了非公版RTX 3080显卡的技术特点和创新设计。 ... [详细]
  • 本文详细介绍 Go+ 编程语言中的上下文处理机制,涵盖其基本概念、关键方法及应用场景。Go+ 是一门结合了 Go 的高效工程开发特性和 Python 数据科学功能的编程语言。 ... [详细]
  • 本文详细介绍如何使用arm-eabi-gdb调试Android平台上的C/C++程序。通过具体步骤和实用技巧,帮助开发者更高效地进行调试工作。 ... [详细]
  • 资源推荐 | TensorFlow官方中文教程助力英语非母语者学习
    来源:机器之心。本文详细介绍了TensorFlow官方提供的中文版教程和指南,帮助开发者更好地理解和应用这一强大的开源机器学习平台。 ... [详细]
  • Explore a common issue encountered when implementing an OAuth 1.0a API, specifically the inability to encode null objects and how to resolve it. ... [详细]
  • 本文详细介绍了如何解决Uploadify插件在Internet Explorer(IE)9和10版本中遇到的点击失效及JQuery运行时错误问题。通过修改相关JavaScript代码,确保上传功能在不同浏览器环境中的一致性和稳定性。 ... [详细]
  • 导航栏样式练习:项目实例解析
    本文详细介绍了如何创建一个具有动态效果的导航栏,包括HTML、CSS和JavaScript代码的实现,并附有详细的说明和效果图。 ... [详细]
  • 本文介绍了如何使用JQuery实现省市二级联动和表单验证。首先,通过change事件监听用户选择的省份,并动态加载对应的城市列表。其次,详细讲解了使用Validation插件进行表单验证的方法,包括内置规则、自定义规则及实时验证功能。 ... [详细]
  • 数据库内核开发入门 | 搭建研发环境的初步指南
    本课程将带你从零开始,逐步掌握数据库内核开发的基础知识和实践技能,重点介绍如何搭建OceanBase的开发环境。 ... [详细]
  • 解决PHP与MySQL连接时出现500错误的方法
    本文详细探讨了当使用PHP连接MySQL数据库时遇到500内部服务器错误的多种解决方案,提供了详尽的操作步骤和专业建议。无论是初学者还是有经验的开发者,都能从中受益。 ... [详细]
author-avatar
一月的泰迪熊
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有