热门标签 | 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 和 事宜流》


推荐阅读
  • DNN Community 和 Professional 版本的主要差异
    本文详细解析了 DotNetNuke (DNN) 的两种主要版本:Community 和 Professional。通过对比两者的功能和附加组件,帮助用户选择最适合其需求的版本。 ... [详细]
  • 本文将介绍如何编写一些有趣的VBScript脚本,这些脚本可以在朋友之间进行无害的恶作剧。通过简单的代码示例,帮助您了解VBScript的基本语法和功能。 ... [详细]
  • 计算机网络复习:第五章 网络层控制平面
    本文探讨了网络层的控制平面,包括转发和路由选择的基本原理。转发在数据平面上实现,通过配置路由器中的转发表完成;而路由选择则在控制平面上进行,涉及路由器中路由表的配置与更新。此外,文章还介绍了ICMP协议、两种控制平面的实现方法、路由选择算法及其分类等内容。 ... [详细]
  • 本文详细探讨了Java中的24种设计模式及其应用,并介绍了七大面向对象设计原则。通过创建型、结构型和行为型模式的分类,帮助开发者更好地理解和应用这些模式,提升代码质量和可维护性。 ... [详细]
  • 数据管理权威指南:《DAMA-DMBOK2 数据管理知识体系》
    本书提供了全面的数据管理职能、术语和最佳实践方法的标准行业解释,构建了数据管理的总体框架,为数据管理的发展奠定了坚实的理论基础。适合各类数据管理专业人士和相关领域的从业人员。 ... [详细]
  • 本文详细介绍了 Dockerfile 的编写方法及其在网络配置中的应用,涵盖基础指令、镜像构建与发布流程,并深入探讨了 Docker 的默认网络、容器互联及自定义网络的实现。 ... [详细]
  • 本文介绍了如何使用JQuery实现省市二级联动和表单验证。首先,通过change事件监听用户选择的省份,并动态加载对应的城市列表。其次,详细讲解了使用Validation插件进行表单验证的方法,包括内置规则、自定义规则及实时验证功能。 ... [详细]
  • 本文详细介绍了Java中org.eclipse.ui.forms.widgets.ExpandableComposite类的addExpansionListener()方法,并提供了多个实际代码示例,帮助开发者更好地理解和使用该方法。这些示例来源于多个知名开源项目,具有很高的参考价值。 ... [详细]
  • 前言--页数多了以后需要指定到某一页(只做了功能,样式没有细调)html ... [详细]
  • 本文详细介绍了Java编程语言中的核心概念和常见面试问题,包括集合类、数据结构、线程处理、Java虚拟机(JVM)、HTTP协议以及Git操作等方面的内容。通过深入分析每个主题,帮助读者更好地理解Java的关键特性和最佳实践。 ... [详细]
  • 尽管某些细分市场如WAN优化表现不佳,但全球运营商路由器和交换机市场持续增长。根据最新研究,该市场预计在2023年达到202亿美元的规模。 ... [详细]
  • 本文介绍如何解决在 IIS 环境下 PHP 页面无法找到的问题。主要步骤包括配置 Internet 信息服务管理器中的 ISAPI 扩展和 Active Server Pages 设置,确保 PHP 脚本能够正常运行。 ... [详细]
  • 题目描述:给定n个半开区间[a, b),要求使用两个互不重叠的记录器,求最多可以记录多少个区间。解决方案采用贪心算法,通过排序和遍历实现最优解。 ... [详细]
  • 探讨一个显示数字的故障计算器,它支持两种操作:将当前数字乘以2或减去1。本文将详细介绍如何用最少的操作次数将初始值X转换为目标值Y。 ... [详细]
  • 深入解析:手把手教你构建决策树算法
    本文详细介绍了机器学习中广泛应用的决策树算法,通过天气数据集的实例演示了ID3和CART算法的手动推导过程。文章长度约2000字,建议阅读时间5分钟。 ... [详细]
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社区 版权所有