Note:Webpack Loader

為什么需要loader?

Webpack 本身能處理 js 和 JSON 文件硫嘶,如果要處理其他類型的模塊锰悼,就需要使用loader來對模塊進行轉換勒极。

loader是什么饲帅?

loader本質上是一個node模塊敞恋,符合Webpack中一切皆模塊的思想丽啡。
loader本身就是一個函數,在該函數中對接收到的內容進行轉換硬猫,然后返回轉換后的結果补箍。

loader的運行機制

loader 是 Webpack 的核心概念之一,它的基本工作流是將一個模塊以字符串的形式讀入啸蜜,對其進行語法分析及轉換坑雅,然后交由下一個環(huán)節(jié)進行處理,所有載入的模塊最終都會經過 moduleFactory 處理衬横,轉成 JavaScript 可以識別和運行的代碼裹粤,從而完成模塊的集成。

loader的特點:

  1. 鏈式調用:第一個loader接收到的是源文件的內容冕香,后續(xù)loader接收到的都是上一個loader 返回的處理結果蛹尝,webpack 會按順序鏈式調用每個 loader;
  2. 單一職責:每個loader 只做一件事悉尾;
  3. 統(tǒng)一原則:遵循 Webpack 制定的設計規(guī)則和結構突那,輸入與輸出均為字符串,各個 Loader 完全獨立构眯,即插即用愕难;
  4. 模塊化:保證 loader 是模塊化的。loader 生成模塊需要遵循和普通模塊一樣的設計原則;
  5. 無狀態(tài):在多次模塊的轉化之間猫缭,我們不應該在 loader 中保留狀態(tài)葱弟。每個 loader 運行時應該確保與其他編譯好的模塊保持獨立,同樣也應該與前幾個 loader 對相同模塊的編譯結果保持獨立猜丹。

loader的執(zhí)行順序:點擊查看文章芝加、Pitching Loader

  • 正常loader的執(zhí)行順序是從右往左(從下往上)。但是loader在處理資源文件時分兩個階段射窒,Pitch階段和Normal階段藏杖;
  • loader本身就是一個方法,pitch是loader這個方法的一個屬性脉顿,pitch也是一個方法蝌麸;
  • Pitch階段:這是loader處理資源文件之前的階段。在這個階段艾疟,loader的pitch方法會按照后置(post)来吩、行內(inline)、普通(normal)蔽莱、前置(pre)的順序被調用弟疆。
  • Normal階段:這是loader對源文件進行轉譯的階段。在這個階段碾褂,loader的常規(guī)方法會按照前置(pre)兽间、普通(normal)、行內(inline)正塌、后置(post)的順序被調用。模塊源碼的轉換恤溶, 就發(fā)生在這個階段乓诽。
  • 如果loader都有Pitch階段和Normal階段,并且Pitch都沒有返回值的話咒程,那么先從左到右(從上到下)執(zhí)行Pitch鸠天,然后再從右到左(從下到上)執(zhí)行l(wèi)oader的源碼轉換。
  • 如果loader都有Pitch階段和Normal階段帐姻,然后某個Pitch有返回值的話稠集,那么當前Pitch的loader和后面的loader、pitch都不會再執(zhí)行了饥瓷。例如:loader1(pitch1)剥纷、loader2(pitch2,pitch2有return返回值)呢铆、loader3(pitch3)晦鞋,此時的執(zhí)行順序是picth1 => pitch2 => loader1

loader的返回值:
loader的原理就是將輸入的源內容進行處理后返回,loader 有兩種方式返回處理后的內容:

1. return source:

module.exports = function (source, sourceMaps) {
    // 在這里按照你的需求處理 source,source是需要處理的內容字符串
    // sourceMaps可以用來調試
    return source.replace('world', 'Ltraveller')
}

2. this.callback():
this.callback()除了可以返回處理過的內容以外悠垛,還可以返回其它信息线定,this.callback() 是 webpack 給 loader 注入的 API,方便 loader 和 webpack之間通信确买。

module.exports = function(source, sourceMaps) { 
   // 通過 this.callback 告訴 Webpack 返回的結果斤讥,還返回了sourceMaps
   this.callback(null, source.replace('world', 'Ltraveller'), sourceMaps);   
   return;
};

this.callback() 的詳細用法如下:

this.callback(    
    // 當無法轉換原內容時,給 Webpack 返回一個 Error   
    err: Error | null,    
    // 原內容經過轉換處理后的新內容    
    content: string | Buffer,    
    // 用于把轉換后的內容得出原內容的 Source Map湾趾,方便調試
    sourceMap?: SourceMap,    
    // 如果本次轉換為原內容生成了 AST 語法樹周偎,可以把這個 AST 返回,以方便之后需要 AST 的 Loader 復用該 AST,以避免重復生成 AST撑帖,提升性能 
    abstractSyntaxTree?: AST
);

同步與異步 loader

  1. 同步loader需要return蓉坎,即使使用this.callback(),也需要return undefined胡嘿,以上都是同步loader蛉艾;
  2. 異步loader 使用 const callback = this.async(),this.async() 將這個 loader 變成是一個異步 loader衷敌。
module.exports = function (source) {
  // 調用 this.async() API勿侯,告訴 webpack本次轉換是異步的,loader 會在 callback 中返回結果 
  const callback = this.async();
  // 使用 setTimeout 模擬異步過程
  setTimeout(() => {
    const content = source.replace('world', 'Ltraveller');
    // 通過 callback 返回執(zhí)行異步后的結果
    callback(null, content);
  }, 3000);
};

Webpack 提供了loader-utils工具可以去獲取loader的options配置缴罗。

const loaderUtils = require('loader-utils')
module.exports = function (source) {
    // 獲取到用戶給當前 Loader 傳入的 options
    const options = loaderUtils.getOptions(this) // 獲取配置的options
    console.log('options-->', options)
    // 在這里按照你的需求處理 source
    return source.replace('world', 'Ltraveller')
}

配置

module: {
    rules: [
        {
            test: /\.js$/,
            use: [
                {
                    loader: path.resolve(__dirname, "./myLoaders/my-loader")
                    options: {
                        flag: true,
                    },
                },
            ],
        },
    ],
},

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末助琐,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子面氓,更是在濱河造成了極大的恐慌兵钮,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,907評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件舌界,死亡現場離奇詭異掘譬,居然都是意外死亡,警方通過查閱死者的電腦和手機呻拌,發(fā)現死者居然都...
    沈念sama閱讀 92,987評論 3 395
  • 文/潘曉璐 我一進店門葱轩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人藐握,你說我怎么就攤上這事靴拱。” “怎么了猾普?”我有些...
    開封第一講書人閱讀 164,298評論 0 354
  • 文/不壞的土叔 我叫張陵袜炕,是天一觀的道長。 經常有香客問我抬闷,道長妇蛀,這世上最難降的妖魔是什么耕突? 我笑而不...
    開封第一講書人閱讀 58,586評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮评架,結果婚禮上眷茁,老公的妹妹穿的比我還像新娘。我一直安慰自己纵诞,他們只是感情好上祈,可當我...
    茶點故事閱讀 67,633評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著浙芙,像睡著了一般登刺。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上嗡呼,一...
    開封第一講書人閱讀 51,488評論 1 302
  • 那天纸俭,我揣著相機與錄音,去河邊找鬼南窗。 笑死揍很,一個胖子當著我的面吹牛,可吹牛的內容都是我干的万伤。 我是一名探鬼主播窒悔,決...
    沈念sama閱讀 40,275評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼敌买!你這毒婦竟也來了简珠?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,176評論 0 276
  • 序言:老撾萬榮一對情侶失蹤虹钮,失蹤者是張志新(化名)和其女友劉穎聋庵,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體芜抒,經...
    沈念sama閱讀 45,619評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡珍策,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,819評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了宅倒。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,932評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡屯耸,死狀恐怖拐迁,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情疗绣,我是刑警寧澤线召,帶...
    沈念sama閱讀 35,655評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站多矮,受9級特大地震影響缓淹,放射性物質發(fā)生泄漏哈打。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,265評論 3 329
  • 文/蒙蒙 一讯壶、第九天 我趴在偏房一處隱蔽的房頂上張望料仗。 院中可真熱鬧,春花似錦伏蚊、人聲如沸立轧。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,871評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽氛改。三九已至,卻和暖如春比伏,著一層夾襖步出監(jiān)牢的瞬間胜卤,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,994評論 1 269
  • 我被黑心中介騙來泰國打工赁项, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留葛躏,地道東北人。 一個月前我還...
    沈念sama閱讀 48,095評論 3 370
  • 正文 我出身青樓肤舞,卻偏偏與公主長得像紫新,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子李剖,可洞房花燭夜當晚...
    茶點故事閱讀 44,884評論 2 354

推薦閱讀更多精彩內容