看完这篇webpackloader,不再怕面试官问了腾讯云开发者社区

下面会从基本使用开始出发,探究一个loader怎么写,并实现raw-loader、json-loader、url-loader、bundle-loader

准备工作:先安装webpack、webpack-cli、webpack-dev-server,后面的实践用到什么再装什么

importtxtfrom"raw-loader!./1.txt";//txt就是这个文件里面所有的内容其实使用webpack.config文件统一配置loader后,最终也是会转成这种方式使用loader再引入的。支持多个loader,语法:loader1!loader2!yourfilename

query替代options

使用loadername!前缀语法:raw-loadera=1&b=2!./1.txt,等价于webpack配置:

const{getOptions}=require("loader-utils");module.exports=function(content){constoptions=getOptions(this)||{};//如果是配置,返回的是options;如果是loadername!语法,返回根据query字符串生成的对象//...};复制代码下文为了方便演示,会多次使用此方法配置loader。如果没用过这种方法的,就当作入门学习吧。搞起~

一个loader是一个导出为函数的js模块,这个函数有三个参数:content,map,meta

我们实现一个最最最简单的,给代码加上一句console的loader:

这两个loader就是读取文件内容,然后可以使用import或者require导入原始文件所有的内容。很明显,原文件被当作js使用的时候,缺少了一个导出语句,loader做的事情就是加上导出语句。

比如有一个这样的txt

thisisatxtfile假如你把它当作js来用,import或者require进来的时候,执行thisisatxtfile这句js,肯定会报错。如果想正常使用,那么这个txt文件需要改成:

//自己写的raw-loaderconst{getOptions}=require("loader-utils");//获取webpack配置的options,写loader的固定套路第一步module.exports=function(content,map,meta){constopts=getOptions(this)||{};constcode=JSON.stringify(content);constisESM=typeofopts.esModule!=="undefined"options.esModule:true;//直接返回原文件内容return`${isESM"exportdefault":"module.exports="}${code}`;};复制代码raw-loader和json-loader几乎都是一样的,他们的目的就是把原文件所有的内容作为一个字符串导出,而json-loader多了一个json.parse的过程

注意:看了一下官方的loader源码,发现它们还会多一个步骤

Unicode字符值

转义序列

含义

类别

\u0008

\b

Backspace

\u0009

\t

Tab

空白

\u000A

\n

换行符(换行)

行结束符

\u000B

\v

垂直制表符

\u000C

\f

换页

\u000D

\r

回车

\u0022

"

双引号(")

\u0027

\‘

单引号(‘)

\u005C

\

反斜杠()

\u00A0

不间断空格

\u2028

行分隔符

\u2029

段落分隔符

\uFEFF

字节顺序标记

我们前面已经实现了raw-loader,这个loader是把原文件里面的内容以字符串形式返回。但是问题来了,有的文件并不是一个字符串就可以解决的了的,比如图片、视频、音频。此时,我们需要直接利用原文件的buffer。恰好,loader函数的第一个参数content,支持string/buffer

如何开启buffer类型的content?

//只需要导出raw为truemodule.exports.raw=trueurl-loader的流程就是,读取配置,是否可以转、怎么转=>读取原文件buffer=>buffer转base64输出=>无法转换的走fallback流程。我们下面实现一个简易版本的url-loader,仅仅实现核心功能

const{getOptions}=require("loader-utils");module.exports=function(content){constoptions=getOptions(this)||{};constmimetype=options.mimetype;constesModule=typeofoptions.esModule!=="undefined"options.esModule:true;//base编码组成:data:[mime类型];base64,[文件编码后内容]return`${esModule"exportdefault":"module.exports="}${JSON.stringify(`data:${mimetype||""};base64,${content.toString("base64")}`)}`;};module.exports.raw=true;复制代码然后,我们随便弄一张图片,import进来试一下:

//loader路径自行修改//img就是一个base64的图片路径,可以直接放img标签使用importimgfrom"../../loaders/my-url-loadermimetype=image!./1.png";至于file-loader,相信大家也有思路了吧,流程就是:读取配置里面的publicpath=>确定最终输出路径=>文件名称加上MD5哈希值=>搬运一份文件,文件名改新的名=>新文件名拼接前面的path=>输出最终文件路径

pitch方法的三个参数:

会经历这样的过程:

如果b-loader里面有一个pitch方法,而且这个pitch方法有返回结果,那么上面这个过程自从经过了b-loader后,就不会再将c-loader入栈

//b-loadermodule.exports=function(content){returncontent;};//没做什么,就透传import进来再export出去module.exports.pitch=function(remainingRequest){//remainingRequest路径要加-!前缀return`importsfrom${JSON.stringify(`-!${remainingRequest}`)};exportdefaults`;};复制代码b-loader的pitch方法有返回结果,会经历这样的过程:

什么情况下需要跳过剩下的loader呢?最常见的,就是动态加载和缓存读取了,要跳过后面loader的计算。bundle-loader是一个典型的例子

bundle-loader实现的是动态按需加载,怎么使用呢?我们可以对react最终ReactDom.render那一步改造一下,换成动态加载react-dom,再体会一下区别

-importReactDomfrom"react-dom";+importLazyReactDomfrom"bundle-loaderlazy&name=reactDom!react-dom";+LazyReactDom(ReactDom=>{+console.log(ReactDom,"ReactDom");ReactDom.render(,document.getElementById("root"));+});可以看见reactdom被隔离开来,动态引入

//获取ChunkNamefunctiongetChunkNameFromRemainingRequest(r){constpaths=r.split("/");letcursor=paths.length-1;if(/^index\./.test(paths[cursor])){cursor--;}returnpaths[cursor];}//原loader不需要做什么了module.exports=function(){};module.exports.pitch=function(remainingRequest,r){//带loadername!前缀的依赖路径consts=JSON.stringify(`-!${remainingRequest}`);//使用注释webpackChunkName来定义chunkname的语法return`exportdefaultfunction(cb){returncb(import(/*webpackChunkName:"my-lazy-${getChunkNameFromRemainingRequest(this.resource)}"*/${s}));}`;};复制代码用法和官方的bundle-loader基本差不多,只是动态import返回一个promise,需要改一下使用方法:

一堆上下文的属性中,我们拿其中一个来实践一下:this.loadModule

loadModule(request:string,callback:function(err,source,sourceMap,module))

loadModule方法作用是,解析给定的request到一个模块,应用所有配置的loader,并且在回调函数中传入生成的source、sourceMap和webpack内部的NormalModule实例。如果你需要获取其他模块的源代码来生成结果的话,你可以使用这个函数。

很明显,这个方法其中一个应用场景就是,在已有代码上注入其他依赖

背景:已有一个api文件api.js

constapi0={log(...args){console.log("apilog>>>",...args);}};module.exports=api0;希望效果:我们使用下面这个a.jsjs文件的时候,可以直接使用api,且不报错

//a.jsexportdefaultfunctiona(){return1;}//其他代码//...api.log("a","b");复制代码因此,我们需要构建的时候loader把api打进去我们的代码里面:

//addapi的loadermodule.exports=function(content,map,meta){//涉及到加载模块,异步loaderconstcallback=this.async();this.loadModule("../src/api.js",(err,source,sourceMap,module)=>{//source是一个module.exports=require(xxx)的字符串,我们需要require那部分callback(null,`constapi=${source.split("=")[1]};${content};`,sourceMap,meta);});return;};复制代码loader写好了,记得去webpack配置里面加上,或者使用loadername!的语法引入a.js(./loaders/addapi!./a.js)

最后我们可以看见成功运行了api.js的log

平时也有一些熟悉的场景,某某某api、某某某sdk、公共utils方法、每一个index页面的pvuv上报等等,需要先把这些js加载执行完或者导入。如果我们懒得一个个文件加import/require语句,就可以用这种方式瞬间完成。这种骚操作的前提是,保证后续同事接手项目难度低、代码无坑。注释、文档、优雅命名都搞起来

THE END
1.我们是否可以通过分析来揭开002726之谜然而,如果仅仅将其视为一般性的编码,那么它就失去了特殊性。因此,让我们深入思考一下。“002726”,作为一个具体实体,其背后的故事是什么?这是一个历史问题,也是个技术挑战。 历史研究方面,我们需要查找有关“002726”的文档资料、文献记载等,以确定它是在何时、何地、何人手里出现过,并且对当时社会产生了什么样https://www.mjwqtvwr.cn/mei-fa-jiao-cheng/520754.html
2.南非国际电话的区号是多少,怎么使用南非所在非洲,英文名South Africa,国际电话区号0027,通常我们把它写成+0027、0027-、(0027)、(0027),当然南非国际区号前面的0是可以忽略,所区号也写成27、+27、27-、(27)、(27),按国际标准写法南非电话号码通常写成也写作"0027-地区号-地本地号码"或"0027-手机号码",例:南非比勒陀利亚 某用户的手机为:0027https://inter.chinawutong.com/news/132806.html
3.数字编码背后的故事002726的秘密解析在这个信息爆炸的时代,数字编码已经成为我们日常生活中不可或缺的一部分。从银行卡号到身份证号,从密码到网络协议,每一个数字编码背后都有其独特的含义和用途。在这篇文章中,我们将深入探讨“002726”这一特殊的六位数编码,它可能代表什么,背后隐藏着怎样的故事? 编https://www.3svb9bc3.cn/xue-shu-huo-dong/393493.html
4.002726数字化时代的物联网编码解密002726背后的科技秘密首先,我们需要了解什么是物联网编码?简单来说,物联网编码就是为不同类型设备、服务或应用程序设计的一套规则,以便它们能够相互理解并进行有效沟通。这套规则通常涉及到消息格式、传输速率、安全性等多个层面。 比如说,在智能家居领域,一台空调可能会使用002726来与中央控制中心交流其运行状态。如果这台空调发生故障,根https://www.nssydxrcs.cn/yang-zhi-ji-shu/396011.html
5.工银财富货币B(002722)基金净值估值行情走势—爱基金工银财富货币B同类平均沪深30010-0710-2111-0411-1812-0212-1612-300.00%-10.00%-5.00%5.00%10.00% 当前基金 PK 沪深300 基金涨幅 阶段涨幅 季度涨幅 年度涨幅 近1周 近1月 近3月 近6月 今年来 近1年 近2年 近3年 阶段涨幅 0.04% 0.15% 0.43% 0.86% 0.03% 1.98% 4.14% 6.20% 同类平均 0.03% https://fund.10jqka.com.cn/002722/
6.中银美元债债券(QDII)美元(002287)基金净值估值138645美元债,可以这么稳!基少成多8109-12 10:02 81274盘点美元债投资的几个坑基少成多8109-11 10:47 7040公告中银美元债债券型证券投资基金(QDII)2024年基金资讯08-31 09:08 8050公告关于中银美元债债券型证券投资基金(QDII)暂停大基金资讯08-29 07:38 https://fund.eastmoney.com/002287.html
7.17桑德MTN001:行使利息递延支付选择权,利息递延至2026年1月11日桑德17桑德MTN001:行使利息递延支付选择权,利息递延至2026年1月11日 启迪环境科技发展股份有限公司发布公告,决定行使“17桑德MTN001”利息递延支付选择权,本期应支付利息总额14913.752万元将递延至2026年1月11日支付。 本文源自:金融界AI电报https://www.163.com/dy/article/JKSUJQ9U0519QIKK.html
8.AGPBI:{“kind”:”error”,”text”:”error:\u0027f1f1f6\uAGPBI: {“kind”:”error”,”text”:”error: \u0027f1f1f6\u0027 is incompatible with attribute android:b 【声明:】本文是作者(蘑菇v5)原创,版权归作者蘑菇v5所有,侵权必究。本文首发在简书。如若转发,请注明作者和来源地址!未经授权,严禁私自转载!https://www.jianshu.com/p/141a36bd204e
9.135.hx把电棒放在B里开电 A站小黄片视频 爆操母狗人妻 女人自慰AV 91性吧在线 呦交小u女国产精品视频l iGIAO视频 美女扒开内裤让我爽了一晩上 XXX.69HD 性感王楚然胸大被艹污污视频在线观看免费 久久国产精品香蕉绿巨人 夏目彩春新电影 欧美性爱另类 性亚洲娇小枯廋 yy欧美一级大片在线观看 十大高钾食物http://135.hx-r.com/xxxr48556793
10.javascriptinput回车js中回车什么符号\v:垂直制表符(\u000B) \':单引号(\u0027) \":双引号(\u0022) \\:反斜杠(\u005C) 反斜杠还有三种特殊用法。 (1)\HHH 反斜杠后面紧跟三个八进制数(000到377),代表一个字符。HHH对应该字符的 Unicode 码点,比如\251表示版权符号。显然,这种方法只能输出256种字符。 https://blog.51cto.com/u_12929/9206998
11.Scala编程基础元组的实际类型取决于它包含的数量和元素以及这些元素的类型。 因此,(99,"Luftballons")的类型是Tuple2 [Int,String]。('u','r',“the”,1,4,"me")是Tuple6 [Char,Char,String,Int,Int,String]。 元组是类型Tuple1,Tuple2,Tuple3等等。目前在Scala中只能有22个上限,如果您需要更多个元素,那么可以使用集https://blog.csdn.net/sp_ur/article/details/82751520
12.职业院校技能大赛高职组(嵌入式系统应用开发赛项)备赛试题库(含下面是一对一维数组s的初始化,其中不正确的是A、chars[5]={"abc"}B、chars[5]={\u0027a\u0027,\u0027b\u0027,\u0027c\u0027}C、hars[5]={""}D、chars[5]={"abcdef"}答案:D49.关于线程说法不正确的是A、在android中,我们可以在主线程中,创建一个新的线程B、在创建的新线程中,它可以操作UIhttps://www.renrendoc.com/paper/346888273.html
13.贵BU0027统一社会信用代码: 92520201MA6GE3TH0U 经营者:周兴玉 关联企业 2 资金数额:- 成立日期: 2008-10-13 电话: 13678588943 邮箱: - 官网: - 地址: 贵州省六盘水市钟山区流动(贵BU0027) 贵B-U0027是?家成?于2008年10月13日的个体工商户,属于以从事交通运输、仓储和邮政业为主的企业。位于六盘https://www.qichacha.com/firm_f1584a119f4a879e01c94b02a1404f3b.html
14.cdjkpx.com/xxxr42277252.shtml淫妇尻B 是什么意思啊打扑克不盖被 韩国GOGO大胆人体艺术 女人让男人桶的动漫在线观看 老外淫虎女人大迟度 扒开bbbbb裸图 朱竹清被插入下体 男操女视频网站 欧美伊人五月 中文字母在线播放视频免费大全网站 亚洲4438 嗯嗯啊啊不要啊视频在线免费 91精品久久久久久久久99绯色 《loveme动漫在线观看免费》日韩http://cdjkpx.com/xxxr42277252.shtml
15.javascript中的转义字符有哪些js教程转义字符是字符的一种间接表示方式,javascript中的转义字符有:“”、“”、“”、“”、“”、“”、“”、“"”、“'”、“\”、“xx”、“uxxxx”、“xxx”。 本教程操作环境:windows7系统、ECMAScript 5版、Dell G3电脑。 转义字符是字符的一种间接表示方式。在特殊语境中,无法直接使用字符自身。例如,https://www.php.cn/faq/473261.html
16.鲁BU0027车牌吉凶:(凶带吉)一盛一衰.可守成功–车主之家车主之家车牌吉凶查询 鲁BU0027车牌吉凶 车牌号码:鲁BU0027 车牌吉凶:凶带吉 吉凶签文:一盛一衰.可守成功 (结果仅供娱乐,切莫当真!)https://app.16888.com/jx/?mod=success&cp=%E9%B2%81BU0027
17.sdzapx.com/xxxr18903926.htm仙踪林1300部小u女 2021蜜芽在线观看永不失联版 国产又粗又硬又大又爽 原神胡桃开襟乳液狂飙纯视频 欧洲suv 中文字幕MIDE-854大嫌い 寝取人妻av中文字幕 艳遇一级毛 亚洲最新色 亚洲精品中文字幕码专区 亚洲草逼xxxx 114大但人文艺术包子铺 喷奶浆视频H 哥弟调教 周妍希在线 我要看A级片啪啪啪操死http://sdzapx.com/xxxr18903926.htm
18.linux命令总结mybloges0007.b删除名为\a的文件(bjchenxu) rm \\a 0007.c删除名字带的/和‘\0'文件(bjchenxu) 这些字符是正常文件系统所不允许的字符,但可能在文件名中产生,如unix下的NFS文件系统在Mac系统上使用 1.解决的方法,把NFS文件系统在挂到不过滤'/'字符的系统下删除含特殊文件名的文件。 https://www.cnblogs.com/bigbean/p/3657482.html
19.阿拉伯语字母表U-04000000 - U-7FFFFFFF: 1111110x10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx xxx 的位置由字符编码数的二进制表示的位填入,越靠右的 x 具有越少的特殊意义,只用最短的那个足够表达一个字符编码数的多字节串。 注意在多字节串中, 第一个字节的开头"1"的数目就是整个串中字节的数目。而第一行中以https://www.pianshen.com/article/78172361800/
20.被渣男劈腿后,我转身招惹顶级豪门大佬公公给儿媳添B 日本熟女俱乐部 欲海潮喷5在线 莉娜安德森番号 麻豆 幼女 国产 暗网猎奇小屋下载 成人 爱爱网站 奶25fC·cC 无毛少女偏爱者 宫交拳交灌精视频 男女同房在线观看 ‘***℉ 的网址分享 ¢U_C4b28321hbY¢ 杰佣r头条文章 10k找--华网优站网 BILIBILI欧一美一交一配一交一http://m.secmug.cn/year/264232
21.www.lingmaoart.com/appnews20569126.htm国产美女日B 男生鸡机机桶女生机机 17.03MB 39%好评0027人) 大美女搞逼黄色三级花带 网红一区在线观看 亚洲性交色视频 32.82MB 29%好评8949人) 国产AV巨作-淫过年上之表兄妹的淫乱新春 - 醉奶吧 日本亚洲视频图片 轻点痛18禁止线看 85.24MB 01%好评22人) 国产男同在线观看 69无人区乱码http://www.lingmaoart.com/appnews20569126.htm
22.Danfoss丹佛斯自动化控制产品(BWTLO)AutomationControl118U0027 118U0028 118U0029 118U0030 118U0031 118U8056 118U8057 118U8058 118U8059 118U8007 8174044 118U8010 8174045 118U3492 118U3494 118U4620 118U4621 084B4189 084B4191 084B4190 118U0049 027B0120 080G1601 118U3846 118U3847 118U3848 118U3849 118U3850 118U3845 017-404166 017-404http://m.fanpaijidian.com/?p=15771