问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

高度概括webpackloader和plugin的区别

发布网友 发布时间:2024-09-27 03:53

我来回答

1个回答

热心网友 时间:2024-10-04 14:22

建议边看文章边动手实践以加强理解

loader和plugin的区别

两者的区别可以从下面几点分析:

概念

用法

执行顺序

如何开发loader和plugin

源码层面

概念上

引用Webpack官网关于loader和plugin的解释:

loader。webpack自带的功能只能处理javaScript和JSON文件,loader让webpack能够去处理其他类型的文件,并将它们转换成有效的模块,以及被添加到依赖图中。

plugin。插件可以执行范围更广的任务,包括打包优化,资源管理,注入环境变量

loader的概念相对容易理解。插件的就比较拗口,其实插件就是暴露了webpack整个打包构建生命周期中的钩子给我们订阅,方便我们监听整个打包过程

用法上loader

有两种方式使用loader:

配置文件

内联方式

配置文件。loader有两个属性:

test属性,识别出哪些文件会被转换

use属性,定义出在进行转换时,应该使用哪个loader。

module.exports?=?{??output:?{????filename:?"my-first-webpack.bundle.js",??},??module:?{????rules:?[{?test:?/\.txt$/,?use:?"raw-loader"?}],??},};内联方式

在每个import语句中显式指定loader

//?inline?loader一样可以传递options,通过?key=value&foo=bar这种方式import?Styles?from?"style-loader!css-loader?modules!./styles.css";plugin。

只需要引入对应的plugin,然后在plugins数组中new一下即可

const?webpack?=?require("webpack");?//?访问内置的插件module.exports?=?{??plugins:?[new?webpack.ProgressPlugin()],};执行顺序plugin

plugin的执行时机和webpack钩子或者其他插件的钩子有关,本质上利用的是Tapable定义的钩子。webpack提供了各种各样的钩子,可以看这里。因此如果想要熟练开发webpack插件,一定要对Tapable用法比较熟悉。我手写了Tapable所有的钩子,解读了Tapable的源码,并提供了使用Demo,具体可以看这里

loader

默认情况下,loader按照我们在配置文件中配置的module.rules从下往上,从右到左依次执行。但是可以通过enforce以及inlineloader修改loader的执行顺序。

rules:?[??{????test:?/\.js$/,????use:?{??????loader:?"loader3",????},????enforce:?"pre",?//?enforce:?'post'??},];loader的分类

按执行顺序,loader可以这么划分:

preLoader。enforce被设置成pre的loader

postLoader。enforce被设置成post的loader

normalloader。在配置文件中配置的并且没有设置enforce属性的普通loader

inlineloader。在import语句中使用的loader

loader的执行顺序

默认情况下,loader按照我们在配置文件中配置的module.rules从下往上,从右到左依次执行。

实际上,loader会按照下面的顺序执行:

先执行preLoader

其次执行normalloader

然后执行inlineloader

最后执行postLoader

inlineloader的使用方式不同,也会改变loader的顺序,这又引入了新的复杂度,可以点击这里查看

如果inlineloader前面只有!号,则文件不会再通过配置的normalloader解析

import?Styles?from?"!style-loader!css-loader?modules!./styles.css";

如果inlineloader前面有!!号,则表示文件不再通过其他loader处理,只经过inlineloader处理。

import?Styles?from?"!!style-loader!css-loader?modules!./styles.css";

如果inline-loader前面有-!,则不会让文件再去通过preLoader以及normalloader解析,但还是会经过postLoader解析

import?Styles?from?"-!style-loader!css-loader?modules!./styles.css";

执行顺序这块建议动手实践一下

如何开发loader和plugin

如何开发loader

如何开发plugin

loader

记住,loader只能是普通函数,不能是箭头函数,因为webpack在运行loader时,会往我们的loader中注入loaderContext上下文,可以点击这里查看。因此loader函数中的this是有意义的,不能使用箭头函数。

loader的组成

loader包含两部分,pitchLoader和normalLoader,pitch和normal的执行顺序正好相反

当pitch没有定义或者没有返回值时,会先依次执行pitch在获取资源执行loader

如果定义的某个pitch有返回值则会跳过读取资源和自己的loader。假设有use:[loader1,loader2,loader3],三个loader都包含pitchloader和normalloader。

第一种情况,三个loader的pitchloader都没有返回值,那么执行顺序为:pitchloader3->pitchloader2->pitchloader1->获取资源->normalloader1->normalloader2->normalloader3

第二种情况,pitchloader有返回值,假设pitchloader2有返回值,则执行顺序为:pitchloader3->pitchloader2->noramlloader3

function?loader(source)?{??console.log("pitchLoader...",?source);}loader.pitch?=?function?()?{??console.log("pitch...");};module.exports?=?loader;

建议动手实践方便比较pitchloader和normalloader的关系。目前我们用的style-loader就使用了pitchloader,具体可以查看我手写的style-loader

plugin

plugin是一个类,其中必须实现一个apply方法,apply方法接收webpack的compiler对象,从中可以定义插件自己的钩子或者订阅其他插件的钩子

//?A?JavaScript?class.class?MyExampleWebpackPlugin?{??//?Define?`apply`?as?its?prototype?method?which?is?supplied?with?compiler?as?its?argument??apply(compiler)?{????//?Specify?the?event?hook?to?attach?to????compiler.hooks.emit.tapAsync(??????"MyExampleWebpackPlugin",??????(compilation,?callback)?=>?{????????console.log("This?is?an?example?plugin!");????????console.log(??????????"Here’s?the?`compilation`?object?which?represents?a?single?build?of?assets:",??????????compilation????????);????????//?Manipulate?the?build?using?the?plugin?API?provided?by?webpack????????compilation.addModule(/*?...?*/);????????callback();??????}????);??}}源码上

从webpack调用loader以及plugin的时机简单介绍

loader

loader的调用在lib/NormalModule中。

webpack在打包我们的源码时,会从入口模块开始构建依赖(主要流程在Compilation.js中)。对每一个文件都会依次执行下面的顺序:

调用NormalModule.build()构建模块(一个文件对应一个NormalModule)

对每一个模块调用runLoaders执行模块匹配的loaders,获取经过loader处理后的模块源码

调用this.parser.parse()解析处理后的模块源码,提取模块依赖

对提取的模块依赖,再重复以上过程

可以看出,loader的执行在依赖解析之前完成

plugin

plugin的调用时机就比较灵活。实际上webpack在整个生命周期都会调用相应的钩子。比如

在根据文件路径解析模块时,会调用相应的resolvers钩子。

假设有个需求,需要分析都有哪些文件引用了product.js这个文件,此时就可以使用resolvers钩子。

总结

综上可以看出,虽然loader的分类,组成,用法比较多样,但是只要理解了这些差异,就能轻松的开发自己的loader。

plugin的组成,用法比较单一,但是如果要自己开发的话还是有难度的。因为需要理解webpack在整个生命周期过程中都暴露了哪些钩子,怎么结合自己的业务需求去使用对应的钩子。

一般来说,看到这里基本就已经熟悉了loader和plugin的区别。如果你不满足于此,可以关注我Github里面的mini-webpack。在这里我不仅手写了常见的loader,比如babel-loader,css-loader,file-loader,less-loader,style-loader以及url-loader。还原汁原味手写了webpack4的主流程源码。如果对源码感兴趣的朋友可以在仓库里面给我提issue一起讨论。

原文:https://juejin.cn/post/7098556679242907662

声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
武汉大学在职研究生考试科目有哪些 报考武汉大学在职研究生录取率高吗? 武汉大学mpa在职研究生好考吗 忘记车子买哪家保险 怎么查 67年的羊和什么生肖最配夫妻 67年的羊和69年鸡相配吗? 67年羊男与69年鸡女同是11月出生婚配如何? 67年9月和69年十月的结婚 “新菊亦侵篱”的出处是哪里 “闲绕篱头看菊花”的出处是哪里 发票什么时间限制 发票有效期是多久? 汽车每年需要交的费用有哪些?如:交强险。。。 ...每年除了交保险费,还需要交其他费用吗?油钱和保养钱除外 ...经常大便不成形,经常傍晚肚子胀难受,身体非常瘦,右肋下侧感觉有个... 飞机为什么 能飞 近期右侧肋骨下方隐痛,疼痛部位偶有转移,大便不成形,不影响夜间睡眠,大 ... 胃泛酸 隐痛 咕噜响 左肋骨下也痛 大便不成形 像挤牙膏... 飞机为什么会飞呢 成年的孩子不听话该怎么管教 右肋下疼痛,大便不畅,不成形,只要大便畅了全身胃口都好了,是怎 22岁的儿子不听话怎么教育成年的儿子不听话解决方法 电脑无法识别声卡是怎么回事? 新买的创新5.1声卡。结果我的电脑一直都... 马上年底了单位直接辞退员工,请问年终奖该怎么办呢? 梦见水泥罐车北分离了、水泥罐在地磅上面、车头在旁边。这个梦有点... 关于庆祝国庆节的英语作文,我要参加作文竞赛,我初二,100词左右,要单词... 一个号码注册了两个微信号怎么找回第一个微信号,密码忘记的情况下 ...号注册了两个微信号,旧的微信号忘记了密码,怎么找回登录,谢谢... 公司试用期为2个月,转正后签订劳动合同,但要满一年才能缴纳五险一金... 小学我们学过的写人的课文有 叙事的课文有 写景的课文有 状物的... 辨别黄茶品质的方法有哪些? 如何选购高品质的黄茶? 有哪些判断黄茶品质的技巧分享? 黄茶的品质好坏受哪些方面的影响 "2 b 青年"这个词语是什么意思? 如何辨别虎山黄茶的品质? 教你如何鉴别黄茶怎样选购好的黄茶 我怎么这么无聊啊 我是普通青年,文艺青年,还是2B青年 品鉴远安黄茶有什么特别的讲究? 开奶茶店需要多少钱装修 想年底的时候把大学英语六级给考了,作文是个大问题,该怎么学? 苹果手机怎么把录音转换成文字 俄狄浦斯情结解读 求通项公式方法汇总 没时间考驾照了 在家报名考驾照剩下一年就要过期了,但没时间回家练习考试,该怎么办呢... 再战江湖自创武功条件 咏雪的古诗句子 龙邦物流有管制的吗?怎么投诉才有效?