探秘 webpack 中 loader 的實(shí)現(xiàn)方式

正值前端組件化開發(fā)時(shí)代踪央,那么必然離不開目前最火的構(gòu)建工具——webpack(grunt,gulp等暫且不談)。說(shuō)到這里,剛好有幾個(gè)問(wèn)題:
  • 為什么運(yùn)行打包命令之后忌卤,.vue 文件可以轉(zhuǎn)成 .js 文件
  • 為什么運(yùn)行打包命令之后,.less 文件可以轉(zhuǎn)成 .css 文件
  • 為什么運(yùn)行打包命令之后楞泼,ES6+ 語(yǔ)法可以轉(zhuǎn)成 ES5 語(yǔ)法

上面這幾個(gè)問(wèn)題驰徊,就引出了我們的主角——【loader】。
loaderwebpack 的一塊很重要的組成部分堕阔。我們都知道 webpack 是用于資源打包的棍厂,里面的所有資源都是“模塊”,內(nèi)部實(shí)現(xiàn)了對(duì)模塊資源進(jìn)行加載的機(jī)制超陆。但是 Webpack 本身只能處理 js 模塊牺弹,如果要處理其他類型的文件,就需要使用 loader 進(jìn)行轉(zhuǎn)換。 Loader 可以理解為是模塊和資源的轉(zhuǎn)換器张漂,它本身是一個(gè)函數(shù)晶默,接收文件源碼作為參數(shù),返回轉(zhuǎn)換的結(jié)果航攒,例如可以使用 loader 加載器可以快速編譯預(yù)處理器 (less,sass,coffeeScript)磺陡。Loader 可以在 require() 引用模塊的時(shí)候添加,也可以在 webpack 全局配置中進(jìn)行綁定屎债,還可以通過(guò)命令行的方式使用仅政。(本篇中的參數(shù)配置及使用方式均基于 webpack4.0 版本)

一、loader的特點(diǎn)

1盆驹、loader 的執(zhí)行順序和代碼書寫的順序是相反的圆丹,即:從下至上,從右至左躯喇。
2辫封、第一個(gè)執(zhí)行的 loader 會(huì)接收源文件做為參數(shù),下一次執(zhí)行的 loader 會(huì)接收前一個(gè) loader 執(zhí)行的返回值做為參數(shù)
3廉丽、需要嚴(yán)格遵循“單一職責(zé)”原則倦微,即每個(gè) loader 只負(fù)責(zé)自己需要負(fù)責(zé)的事情

二、loader API

methods 含義
this.request 被解析出來(lái)的 request 字符串正压。例子:"/abc/loader1.js?xyz!/abc/node_modules/loader2/index.js!/abc/resource.js?rrr"
this.loaders 所有 loader 組成的數(shù)組欣福。它在 pitch 階段的時(shí)候是可以寫入的。
this.loaderIndex 當(dāng)前 loader 在 loader 數(shù)組中的索引焦履。
this.async 告訴 loader-runner 這個(gè) loader 將會(huì)異步地回調(diào)
this.callback 一個(gè)可以同步或者異步調(diào)用的可以返回多個(gè)結(jié)果的函數(shù)
this.data 在 pitch 階段和正常階段之間共享的 data 對(duì)象拓劝。
this.cacheable 設(shè)置是否可緩存標(biāo)志的函數(shù)
this.resource request 中的資源部分,包括 query 參數(shù)
this.resourcePath 資源文件的路徑嘉裤。
this.resourceQuery 資源的 query 參數(shù)
this.target 編譯的目標(biāo)郑临。從配置選項(xiàng)中傳遞過(guò)來(lái)的。
this.webpack 如果是由 webpack 編譯的屑宠,這個(gè)布爾值會(huì)被設(shè)置為真
this.sourceMap 應(yīng)該生成一個(gè) source map厢洞。因?yàn)樯?source map 可能會(huì)非常耗時(shí),你應(yīng)該確認(rèn) source map 確實(shí)有必要請(qǐng)求典奉。
this.emitWarning 發(fā)出一個(gè)警告躺翻。
this.emitError 發(fā)出一個(gè)錯(cuò)誤。
this.loadModule 解析給定的 request 到一個(gè)模塊卫玖,應(yīng)用所有配置的 loader 获枝,并且在回調(diào)函數(shù)中傳入生成的 source 、sourceMap 和 模塊實(shí)例(通常是 NormalModule 的一個(gè)實(shí)例)骇笔。如果你需要獲取其他模塊的源代碼來(lái)生成結(jié)果的話省店,你可以使用這個(gè)函數(shù)嚣崭。
this.resolve 像 require 表達(dá)式一樣解析一個(gè) request 。
this.emitFile 產(chǎn)生一個(gè)文件懦傍。這是 webpack 特有的雹舀。
this.fs 用于訪問(wèn) compilation 的 inputFileSystem 屬性。
this.value 向下一個(gè) loader 傳值粗俱。如果你知道了作為模塊執(zhí)行后的結(jié)果说榆,請(qǐng)?jiān)谶@里賦值(以單元素?cái)?shù)組的形式)。
this.inputValue 從上一個(gè) loader 那里傳遞過(guò)來(lái)的值寸认。如果你會(huì)以模塊的方式處理輸入?yún)?shù)签财,建議預(yù)先讀入這個(gè)變量(為了性能因素)。
更多詳細(xì)API偏塞,以及各API的用法示例唱蒸,可以訪問(wèn)官網(wǎng)查看。地址:https://www.webpackjs.com/api/loaders

三灸叼、寫loader之前的需求整理

現(xiàn)在有這樣一個(gè)需求神汹,使用 hxkj-loader 加載并處理名稱為 *.hxkj.vip 的文件,將里面的哈瞎沤瘢空間全部替換為 www.hxkj.vip屁魏。需要實(shí)現(xiàn)的轉(zhuǎn)換如下:

轉(zhuǎn)換前的內(nèi)容:

<div>
    <h1>歡迎訪問(wèn)哈希空間</h1>
    <p>哎喲捉腥,終于等到你氓拼。這里就是讓人流連忘返的哈希空間呀抵碟!</p>
</div>

轉(zhuǎn)換后的內(nèi)容:

<div>
    <h1>歡迎訪問(wèn)www.hxkj.vip</h1>
    <p>哎喲披诗,終于等到你。這里就是讓人流連忘返的www.hxkj.vip呀立磁!</p>
</div>

四、編寫loader

在與 webpack.config.js 同級(jí)目錄下新建 hxkj-loader.js剥槐,文件的內(nèi)容如下:

module.exports = function(source){
    var content="";
    content = source.replace("/哈铣纾空間/g","www.hxkj.vip");
    return content; 
}

接下來(lái),需要在 webpack.config.js 文件中增加以下的配置:

const path = require("path"); // 引入 node 的 path 模塊
...
module:{
    rules:[{
        test: /\.hxkj\.vip$/, // 正則匹配以 hxkj.vip 結(jié)尾的文件
        use:[{
            loader:path.resolve(__dirname, "hxkj-loader") // 使用 path 模塊找到 hxkj-loader 的路徑
        }]
    }]
}
好粒竖,到此颅崩,一個(gè)簡(jiǎn)易版的 loader 就已經(jīng)寫完了。目前 loader 是直接寫在本地的蕊苗,可以考慮將自己寫好的 loader 發(fā)布到 npm沿后,這樣就更加完善了。

At last朽砰,看完之后有什么不懂的尖滚,可以留言反饋喉刘。

轉(zhuǎn)載請(qǐng)注明出處:http://www.reibang.com/p/51b793f6fa0e
作者:TSY
個(gè)人空間:https://hxkj.vip

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市漆弄,隨后出現(xiàn)的幾起案子睦裳,更是在濱河造成了極大的恐慌,老刑警劉巖撼唾,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件廉邑,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡倒谷,警方通過(guò)查閱死者的電腦和手機(jī)蛛蒙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)渤愁,“玉大人牵祟,你說(shuō)我怎么就攤上這事『锪妫” “怎么了课舍?”我有些...
    開封第一講書人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)他挎。 經(jīng)常有香客問(wèn)我筝尾,道長(zhǎng),這世上最難降的妖魔是什么办桨? 我笑而不...
    開封第一講書人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任筹淫,我火速辦了婚禮,結(jié)果婚禮上呢撞,老公的妹妹穿的比我還像新娘损姜。我一直安慰自己,他們只是感情好殊霞,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開白布摧阅。 她就那樣靜靜地躺著,像睡著了一般绷蹲。 火紅的嫁衣襯著肌膚如雪棒卷。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,631評(píng)論 1 305
  • 那天祝钢,我揣著相機(jī)與錄音比规,去河邊找鬼。 笑死拦英,一個(gè)胖子當(dāng)著我的面吹牛蜒什,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播疤估,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼灾常,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼霎冯!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起岗憋,我...
    開封第一講書人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤肃晚,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后仔戈,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體关串,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年监徘,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了晋修。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡凰盔,死狀恐怖墓卦,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情户敬,我是刑警寧澤落剪,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站尿庐,受9級(jí)特大地震影響忠怖,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜抄瑟,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一凡泣、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧皮假,春花似錦鞋拟、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至褪测,卻和暖如春猴誊,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背汰扭。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留福铅,地道東北人萝毛。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像滑黔,于是被迫代替她去往敵國(guó)和親笆包。 傳聞我的和親對(duì)象是個(gè)殘疾皇子环揽,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355