Webpack Loader源碼導(dǎo)讀之less-loader

原文地址:http://hiihl.com/articles/2018/1/17/lessloader.md

本篇是Webpack Loader源碼導(dǎo)讀系列中關(guān)于less-loader的解讀,主要闡述loader的工作,less編譯部份的內(nèi)容未來將單獨講解。

源碼結(jié)構(gòu)

源碼 v4.0.5,src目錄如下:

src
|____cjs.js
|____createWebpackLessPlugin.js
|____formatLessError.js
|____getOptions.js
|____index.js
|____processResult.js
|____removeSourceMappingUrl.js
|____stringifyLoader.js

options說明

進(jìn)入index.js首先看到的是getOptions(loaderContext),這一步的作用是將webpack相關(guān)配置及l(fā)oader的query或options部份配置合并,得到編譯過程的可選項

  • paths 模塊解析的路徑,默認(rèn)使用webpack的resolver,必須是個絕對路徑數(shù)組;舉例,在less中我們想引用node_modules下bootstrap的less文件,可以這樣寫
    @import "~bootstrap/less/bootstrap";,默認(rèn)的模塊解析將和webpack一致,但如果loader配置paths,則webpack的解析路徑和alias配置在這里將無效。
  • plugins 數(shù)組,編譯時使用的插件,已有的插件見plugins
  • sourceMap 源碼映射,需要同css-loader一同配置;可以是boolean類型,也可以是對象,sourceMap相關(guān)配置如下:
    • {String} sourceMapFilename,對應(yīng)lessc中屬性值為String的--source-map選項;
    • {String} sourceMapRootPath,對應(yīng)lessc的--source-map-rootpath選項;
    • {String} sourceMapURL,對應(yīng)lessc的--source-map-url選項;
    • {String} sourceMapBasePath,對應(yīng)lessc的--source-map-basepath選項;
    • {Boolean} sourceMapLessInline 對應(yīng)lessc的--source-map-less-inline選項;
    • {Boolean} sourceMapMapInline 對應(yīng)lessc的--source-map-map-inline選項;
    • {Boolean} outputSourceFiles 對應(yīng)lessc的--source-map-map-inline選項;注意在less-loader中會將該值默認(rèn)設(shè)置成true。

less-loader其他的配置,都可以從less的配置選項中找到,全部轉(zhuǎn)成駝峰式即可。

有兩個重要的配置globalVarsmodifyVars,這兩個是用于添加或修改less變量的,一起看個例子。

main.less

@import "./other.less";

.box:extend(.hotpink) {
  width: @boxWidth;
  height: @boxHeight;
}

other.less

@boxHeight: 10px;

.hotpink {
  background: hotpink;
  width: @boxWidth;
}

上面的例子中,other.less中定義了變量@boxHeight在main.less中會使用到,值為10px;main.less和other.less中都使用到了@boxWidth,但是并沒有定義;
現(xiàn)在我們在webpack.config.js中配置

{
  loader: "less-loader",
  query: {
    sourceMap: true,
    globalVars: {
      "boxWidth": '200px'
    },
    modifyVars: {
      "boxHeight": '200px'
    }
  }
}

最后編譯沒有出錯,結(jié)果為

.hotpink,
.box {
  background: hotpink;
  width: 200px;
}
.box {
  width: 200px;
  height: 200px;
}

在這個例子中,globalVars的作用相當(dāng)于給每個less文件頂部增加一行@boxWidth: 200px,所以編譯出來的width都為200px,而modifyVars的作用相當(dāng)于在
每個文件底部增加一行@boxHeight: 200px,這樣就會覆蓋已有的@boxHeight: 10px,所以最后編譯出來的height是200px而不是10px;

這有什么作用呢?
有了這兩個配置項,我們就可以把部份樣式抽出變量,通過不同的變量組合成不同的主題,例如:
default.less

@primary-color: #003cee;

themes/pink.js

module.exports = {
  "@primary-color": 'pink'
};

webpack.config.js

{
  loader: 'less-loader',
  query: {
    modifyVars: require('./themes/pink')
  }
}

loader中解析了配置以后,就直接調(diào)用了less的render方法進(jìn)行編譯,render方法有三個入?yún)?code>var render = function (input, options, callback),
第三個參數(shù)是個callback,看render.js源碼可以知道,如果不傳callback,則render方法會返回一個promise。

編譯結(jié)果處理

看下processResult.js如何處理編譯結(jié)果,resultPromise就是前面提到的render返回的promise。

function processResult(loaderContext, resultPromise) {
  const { callback } = loaderContext;

  resultPromise
    .then(({ css, map, imports }) => {
      imports.forEach(loaderContext.addDependency, loaderContext);
      return {
        // Removing the sourceMappingURL comment.
        // See removeSourceMappingUrl.js for the reasoning behind this.
        css: removeSourceMappingUrl(css),
        map: typeof map === 'string' ? JSON.parse(map) : map,
      };
    }, (lessError) => {
      throw formatLessError(lessError);
    })
    .then(({ css, map }) => {
      callback(null, css, map);
    }, callback);
}

編譯后的結(jié)果包括css,map和imports三個,css是less編譯成的css內(nèi)容,map則是sourceMap相關(guān)信息,imports是編譯過程中所有的依賴文件路徑。
拿到編譯結(jié)果后,首先是調(diào)用addDependency把所有imports中的文件添加到依賴?yán)锩?,這個方法的作用時在watch模式時,依賴的這些文件變化時會出發(fā)編譯更新。
然后是removeSourceMappingUrl(css),這個方法的作用是移除結(jié)果中的sourceMappingURL=,理由是less-loader無法知道最終的sourceMap會在哪里。
最后調(diào)用callback(null, css, map)把結(jié)果傳給下一個loader去執(zhí)行,less-loader的的工作就完成了。

下一篇我們將繼續(xù)將css-loader,如何繼續(xù)處理less-loader編譯出來的結(jié)果。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,156評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,401評論 3 415
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 176,069評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,873評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 71,635評論 6 408
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,128評論 1 323
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,203評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,365評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,881評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,733評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,935評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,475評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,172評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,582評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,821評論 1 282
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,595評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 47,908評論 2 372

推薦閱讀更多精彩內(nèi)容

  • 無意中看到zhangwnag大佬分享的webpack教程感覺受益匪淺,特此分享以備自己日后查看,也希望更多的人看到...
    小小字符閱讀 8,206評論 7 35
  • GitChat技術(shù)雜談 前言 本文較長,為了節(jié)省你的閱讀時間,在文前列寫作思路如下: 什么是 webpack,它要...
    蕭玄辭閱讀 12,704評論 7 110
  • 最近在學(xué)習(xí) Webpack,網(wǎng)上大多數(shù)入門教程都是基于 Webpack 1.x 版本的,我學(xué)習(xí) Webpack 的...
    My_Oh_My閱讀 8,199評論 40 247
  • 《紫薇花開了》 那一樹花是什么時候開的 昨夜我還在它的脈河里游泳 去年的秋波忘了蕩漾 致使一個冬天筋絡(luò)漲的又酥又麻...
    陳皮朵娃閱讀 396評論 0 0
  • 沒有風(fēng)的院子 陽光安靜地灑滿每個角落 公婆坐在陽光里 晾曬著屬于他們的慈祥 時間 變得溫柔似水 院子里捉蟲的雞 成...
    明月穿行閱讀 341評論 2 6