從零開(kāi)始寫(xiě)一個(gè)babel插件

babel對(duì)于一個(gè)前端應(yīng)該并不陌生,在我們隨心所欲的使用ESnext的語(yǔ)法的時(shí)候,babel為我們默默的做著轉(zhuǎn)換工作。那我們可能會(huì)好奇babel到底是怎么做到的呢,接下來(lái)我們就從手寫(xiě)一個(gè)babel插件入手來(lái)一起學(xué)習(xí)學(xué)習(xí)。

首先我們要研究一個(gè)東西得弄清楚它到底是干什么,引用babel官網(wǎng)的描述:


圖一

我們首先思考一下babel要將最新的語(yǔ)法進(jìn)行轉(zhuǎn)換,肯定是有一套描述語(yǔ)法的數(shù)據(jù)結(jié)構(gòu),是的它就是AST(抽象語(yǔ)法樹(shù)),看到這玩意是不是有點(diǎn)有頭緒了。有了AST,數(shù)據(jù)結(jié)構(gòu)我們就有了,剩下的就剩匹配轉(zhuǎn)換了。

開(kāi)始寫(xiě)代碼之前我們先來(lái)介紹一下babel提供的工具:

1.https://astexplorer.net/ (在線js代碼轉(zhuǎn)換為AST)

2.babylon(js轉(zhuǎn)換為AST的庫(kù))

3.babel-traverse(AST遍歷庫(kù))

4.babel-types(包含了構(gòu)造、驗(yàn)證以及變換 AST 節(jié)點(diǎn)的方法)

工欲善其事必先利其器,我們的工具都有了,接下來(lái)我們創(chuàng)建一個(gè)項(xiàng)目,項(xiàng)目的目錄結(jié)構(gòu)如下:


圖二

index.js就是我們的插件入口,_test_為單元測(cè)試,test.js是我們需要轉(zhuǎn)換的文件。接下來(lái)我們一起來(lái)看一看index.js文件


圖三

我們這個(gè)插件主要功能是實(shí)現(xiàn)按照配置去除代碼中的console,debugger,以及自定義的一個(gè)DEBUG的一個(gè)調(diào)試關(guān)鍵字(用于在指定環(huán)境下需要執(zhí)行的代碼)。

我們可以看到這邊導(dǎo)出了一個(gè)function,function返回的是一個(gè)對(duì)象,這個(gè)對(duì)象內(nèi)部有一個(gè)visitor屬性,這visitor也是我們最核心的一個(gè)屬性(AST的訪問(wèn)者),這個(gè)訪問(wèn)者是必須要提供的,也可以理解為固定寫(xiě)法。

我們看到導(dǎo)出的function有一個(gè)參數(shù)t,這個(gè)t是干什么的呢?這其實(shí)就是我們上面提到的babel-types。它可以讓我們更方便的去匹配(if, else, for)這些關(guān)鍵字,從而定位到需要執(zhí)行我們自己邏輯的代碼塊。

那visitor內(nèi)部的這些東西又是什么呢,這個(gè)我們就得打開(kāi)我們上面提到的AST轉(zhuǎn)換網(wǎng)站,將我們需要處理的代碼貼進(jìn)去觀察


圖四

以debugger為例,我們看到debugger對(duì)應(yīng)的AST里面的key為DebuggerStatement,然后我們?cè)趘isitor里面也看到了DebuggerStatement,是不是有點(diǎn)眉目了,沒(méi)錯(cuò),這個(gè)key其實(shí)也是做類(lèi)型匹配的。比如debugger,我們就可以在DebuggerStatement內(nèi)去處理自己的邏輯,DebuggerStatement的value是一個(gè)function,提供有兩個(gè)參數(shù)(path, state)path就是當(dāng)前配備到的節(jié)點(diǎn)上下文,state我們經(jīng)常的用法是獲取babel插件配置的參數(shù)。到了這一步,我們回憶我們的需求:根據(jù)配置是否去除(debugger, console, 自定義關(guān)鍵字),現(xiàn)在配置能拿到了,接下來(lái)就是如何去除,這就得在path上面研究了,查詢文檔我們可以看到path提供了replaceWith,remove方法(nice),那我們的思路就很清晰了,匹配到關(guān)鍵字,刪除就OK了。

接下來(lái)修改我們的package.json文件:

圖五

npm run babel,可以看到這個(gè)插件完美的實(shí)現(xiàn)了我們的需求.。對(duì)于關(guān)鍵字和console的處理基本大同小異,需要注意的是自定義關(guān)鍵字需要處理eslint校驗(yàn)。最后附上完整代碼地址:https://github.com/wangKXX/babel-plugin

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容