webpack處理文件內(nèi)容——babel插件保姆級教學

此篇為webpack處理文件內(nèi)容——編寫postcss8.0插件姐妹篇

本文目標

探究編寫一個babel插件顺献,將代碼里的http:轉(zhuǎn)成https:

前言

webpack的babel原理好多博客都有講,Babel 插件手冊里面說

Babel 的三個主要處理步驟分別是:解析(parse),轉(zhuǎn)換(transform)的畴,生成(generate)

解析步驟接收代碼并輸出 AST。 這個步驟分為兩個階段:詞法分析(Lexical Analysis)語法分析(Syntactic Analysis)宗挥。

轉(zhuǎn)換步驟接收 AST 并對其進行遍歷厢呵,在此過程中對節(jié)點進行添加、更新及移除等操作俺夕。

代碼生成步驟把最終(經(jīng)過一系列轉(zhuǎn)換之后)的 AST 轉(zhuǎn)換成字符串形式的代碼,同時還會創(chuàng)建源碼映射(source maps)喷橙。

其實就是code->AST->對AST操作->生成code

那么問題來了啥么,如何對AST進行操作?

AST

用這個網(wǎng)站可以將代碼轉(zhuǎn)成AST:https://astexplorer.net/

  • 代碼
    有鏈接的情況一種是定義了一個變量然后給他賦值贰逾,一種是直接跳轉(zhuǎn)悬荣。
const AURL = 'http://XXXXX';
const BURL = 'http://XX.XXX';
function jump(path) {
    window.location.href = path;
}
jump(AURL);
window.location.href = 'http://XXXXX';
  • 效果



    還挺好使的 - -


    在這里就是我想處理的內(nèi)容
  • 簡單說
    這段代碼里聲明并賦值了一個值為鏈接的變量,然后從這個AST里我知道了這個語句的type為VariableDeclaration疙剑,babel的插件可以針對type為這個的節(jié)點做處理

開始寫插件

Visitors訪問者

寫一個自己的插件之前氯迂,還記得怎么給babel使用插件嗎?來復(fù)習一下吧言缤。假設(shè)我們的插件即將放在根目錄的plugins文件夾里嚼蚀,叫tran-http-plugin

  • 在webpack.config.js里
module: {
  rules: [
    {
      test: /\.js$/,
      exclude: /node_modules/,
      use: {
        loader: 'babel-loader',
      }
    }
  ]
}
  • 在.bablerc或者是babel.config.json里有plugins屬性
 "plugins": ["plugins/tran-http-plugin"]
  • 然后我們寫一下插件內(nèi)容,我喜歡邊調(diào)試邊寫管挟,插件書寫規(guī)則大致如下
    a. 導(dǎo)出一個函數(shù)轿曙,函數(shù)返回體是一個對象
    b. visitor是訪問者,可以在這個對象里面定義訪問節(jié)點的方法
    c. 想處理什么類型的節(jié)點,就找出他們的名字导帝,作為屬性將方法寫在visitor里守谓。
    舉個例子:
    比如說Identifier就是一種節(jié)點的類型,它翻譯過來就是識別碼您单。
    代碼里有一個聲明語句斋荞,聲明了變量AURL并對其賦值。
    那么這個語句的語法樹里會有Identifier這個節(jié)點虐秦,并且node.name="AURL"平酿。我們可以在這里對變量名做一些修改操作。
module.exports = function ({ types: t }) {
    return {
        visitor: {
            Identifier(path) {
                console.log('Visiting: ' + path.node.name);
            },
            VariableDeclaration(path, state) {
                console.log('VariableDeclaration');
            },
        },
    };
};
  • 調(diào)試
    調(diào)試這個腳本悦陋,類似于調(diào)試node一樣蜈彼,很簡單。 不會的可以參考這篇 叨恨。
    觀察控制臺
  • 觀察節(jié)點
    直觀感受柳刮,就是訪問到聲明語句的時候才會進VariableDeclaration里。
    再展開痒钝,要改的部分其實是里面的StringLiteral秉颗,那么我們就可以在這里面對這個節(jié)點進行操作。



    因為這是個語法樹的關(guān)系送矩,所以我們要用操作語法樹的方法去操作節(jié)點蚕甥。

改變節(jié)點

在上一個環(huán)節(jié)我們找到了想改的內(nèi)容


關(guān)鍵點
思路

建一個一樣的節(jié)點,然后替換他栋荸!

構(gòu)建節(jié)點

這里我們用到的是@babel/types 插件菇怀,各種節(jié)點的說明文檔在此
這個文檔反正挺惜字如金的

以這個賦值語句為例分析

const AURL = 'http://XXXXX';
  1. 如何快速定位晌块?變量聲明節(jié)點的構(gòu)成是什么爱沟?
    如果打開文檔,就會發(fā)現(xiàn)節(jié)點多得數(shù)不清匆背,完全不曉得我們要從哪里下手去構(gòu)建這個聲明語句的node呼伸。

在寫代碼之前,我們先了解一下賦值語句的語法節(jié)點構(gòu)成吧钝尸。

對于賦值語句括享,可以從斷點的那個path看出關(guān)鍵詞。搜一下declarations這個單詞珍促,有且只有兩個相關(guān)節(jié)點铃辖。

variableDeclaration:t.variableDeclaration(kind, declarations)
variableDeclarator:t.variableDeclarator(id, init)

得出推論
a. 一個變量聲明語句節(jié)點為variableDeclaration,kind為這個變量的類型猪叙,var娇斩、const這種仁卷,declarations是一個數(shù)組(Array<VariableDeclarator>)。
b. 每一個VariableDeclarator擁有自己的id和init屬性成洗。從調(diào)試結(jié)果來看五督,在這個賦值語句中,id就是Identifier節(jié)點瓶殃,init是StringLiteral節(jié)點。

綜上副签,一個賦值語句的語法樹會出現(xiàn)variableDeclaration遥椿、VariableDeclaratorIdentifier淆储、StringLiteral這四種節(jié)點冠场。
————————
賦值語句節(jié)點偽代碼如下

variableDeclaration(kind,[
    VariableDeclarator(Identifier,StringLiteral)
])
  1. 怎么寫
    我們要操作的其實是stringLiteral,這里是等號右邊那個值本砰。把這個字符串替換掉碴裙。
    在上面的截圖里也有體現(xiàn)了,完整代碼如下
// tran-http-plugin.js
module.exports = function ({ types: t }) {
    return {
        visitor: {
            Identifier(path) {
                console.log('Visiting: ' + path.node.name);
            },
            StringLiteral(path) {
                var node = path.node;
                var oldVal = node.value;
                var matchRes = oldVal.match(/http:\/\/([\w.]+\/?)\S*/);
                var newVal = '';
                if (!matchRes) return;
                newVal = oldVal.replace(/http:\/\//g, 'https://');
                path.replaceWith(t.StringLiteral(newVal));
            },
        },
    };
};
  1. 打包結(jié)果
  • 源文件
const AURL = 'http://XXXXX';
const BURL = 'http://XX.XXX';
function jump(path) {
    window.location.href = path;
}
jump(AURL);
window.location.href = 'http://XXXXX';
  • 轉(zhuǎn)換后


參考資料:
babel腳本文檔
https://zhuanlan.zhihu.com/p/84799735
http://www.reibang.com/p/7c8c5ae1e4be
https://www.csdn.net/gather_2b/MtTacg0sMzQwNzYtYmxvZwO0O0OO0O0O.html
http://www.reibang.com/p/44c0075fd043

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末点额,一起剝皮案震驚了整個濱河市舔株,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌还棱,老刑警劉巖载慈,帶你破解...
    沈念sama閱讀 206,482評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異珍手,居然都是意外死亡办铡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評論 2 382
  • 文/潘曉璐 我一進店門琳要,熙熙樓的掌柜王于貴愁眉苦臉地迎上來寡具,“玉大人,你說我怎么就攤上這事稚补⊥” “怎么了?”我有些...
    開封第一講書人閱讀 152,762評論 0 342
  • 文/不壞的土叔 我叫張陵孔厉,是天一觀的道長拯钻。 經(jīng)常有香客問我,道長撰豺,這世上最難降的妖魔是什么粪般? 我笑而不...
    開封第一講書人閱讀 55,273評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮污桦,結(jié)果婚禮上亩歹,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好小作,可當我...
    茶點故事閱讀 64,289評論 5 373
  • 文/花漫 我一把揭開白布亭姥。 她就那樣靜靜地躺著,像睡著了一般顾稀。 火紅的嫁衣襯著肌膚如雪达罗。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,046評論 1 285
  • 那天静秆,我揣著相機與錄音粮揉,去河邊找鬼。 笑死抚笔,一個胖子當著我的面吹牛扶认,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播殊橙,決...
    沈念sama閱讀 38,351評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼辐宾,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了膨蛮?” 一聲冷哼從身側(cè)響起叠纹,我...
    開封第一講書人閱讀 36,988評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎鸽疾,沒想到半個月后吊洼,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,476評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡制肮,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,948評論 2 324
  • 正文 我和宋清朗相戀三年冒窍,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片豺鼻。...
    茶點故事閱讀 38,064評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡综液,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出儒飒,到底是詐尸還是另有隱情谬莹,我是刑警寧澤,帶...
    沈念sama閱讀 33,712評論 4 323
  • 正文 年R本政府宣布桩了,位于F島的核電站附帽,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏井誉。R本人自食惡果不足惜蕉扮,卻給世界環(huán)境...
    茶點故事閱讀 39,261評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望颗圣。 院中可真熱鬧喳钟,春花似錦屁使、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至易茬,卻和暖如春酬蹋,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背抽莱。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評論 1 262
  • 我被黑心中介騙來泰國打工除嘹, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人岸蜗。 一個月前我還...
    沈念sama閱讀 45,511評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像叠蝇,于是被迫代替她去往敵國和親璃岳。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,802評論 2 345