本文將以把es6的語法let
改成var
爲例,講述如何編寫一個babel插件。其中涉及到一些babel的基本知識,babel的工做流程,語法抽象樹等。前端
關於babel 官網作了以下解釋:node
Babel 是一個工具鏈,主要用於在舊的瀏覽器或環境中將 ECMAScript 2015+ 代碼轉換爲向後兼容版本的 JavaScript 代碼react
相信你們在開發中或多或少的都使用過bable
對代碼進行編譯。在babel配置文件.babelrc
中最主要就是對presets
和Plugins
的配置。其中presets
通俗來講就是某一類的插件轉譯集合,好比說babel官方封裝好的@babel/preset-react
中就包括如下插件@babel/plugin-syntax-jsx
,@babel/plugin-transform-react-jsx
,@babel/plugin-transform-react-display-name
。而Plugins相對來講功能比較單一,好比transform-es2015-arrow-functions
,這個插件只負責轉譯es2015新增的箭頭函數。es6
因此在咱們的平常開發中也能夠根據本身的需求開發bebal插件,從而提升開發效率。編程
Babel轉碼的過程分三個階段:解析(parse)、轉換(transform)、生成(generate)。下面這張圖能夠很好的說明babel的工做過程瀏覽器
其中,解析、生成階段由Babel核心完成,而轉換階段,則由Babel插件完成,這也是本文的重點。bash
在計算機科學中,抽象語法樹(Abstract Syntax Tree,AST),或簡稱語法樹(Syntax tree),是源代碼語法結構的一種抽象表示。它以樹狀的形式表現編程語言的語法結構,樹上的每一個節點都表示源代碼中的一種結構。之因此說語法是「抽象」的,是由於這裏的語法並不會表示出真實語法中出現的每一個細節。微信
開發一個babel插件必定要對AST有所瞭解,上面是維基百科對抽象語法樹的解釋babel
舉個例子:編程語言
var a = 1;
複製代碼
轉換成的AST結構爲:
這裏是能夠實時查看代碼ast結構的網站astexplorer.net/,有助於更好的瞭解ast以及編寫babel插件
可用於從命令行編譯文件
"@babel/cli": "^7.1.5",
"@babel/core": "^7.1.6",
複製代碼
新建一個babel-letToVar.js
文件,代碼以下
function letToVar(babel) {
const { types: t, template } = babel;
return visitor = { };
}
module.exports = letToVar;
複製代碼
咱們能夠在letToVar
這個方法中接收babel對象。
visitor 屬性是這個插件的主要訪問者,且其中的每一個函數接收2個參數:path 和 stat。訪問者是一個用於 AST 遍歷的跨語言的模式。簡單的說它們就是一個對象,定義了用於在一個樹狀結構中獲取具體節點的方法。
咱們的需求是將let
轉換成var
,那麼咱們須要添加一個VariableDeclaration
訪問者方法
function letToVar(babel) {
const { types: t, template } = babel;
const visitor = {
VariableDeclaration(path) {
if(path.get('kind').node!='let')return;
path.node.kind='var';
}
};
return {visitor};
}
module.exports = letToVar;
複製代碼
咱們能夠經過path.get()方法獲取到kind,並判斷他是否是爲let,若是是就將其改成var,以實現咱們的需求。
下面咱們能夠運行看一下效果是否符合咱們的預期。
.eslintrc
文件咱們能夠直接在此文件中引入咱們的babel-letToVar.js文件
{
"plugins": [ "./babel-letToVar.js"]
}
複製代碼
咱們能夠在終端運行下面命令,將inedx.js文件編譯後輸出到dest.js文件中。
$ babel index.js --out-file dest.js
複製代碼
下圖是運行效果,能夠看到已經實現了咱們的需求。
本文演示的只是一個簡單的babel插件的開發,咱們在轉換的過程當中拿到代碼的AST結構後,就能夠爲所欲爲的對代碼進行增長、刪除、修改。咱們還能夠經過編寫babel插件實現更多的功能,好比刪除代碼中全部console.log
等。
卓月,銅板街前端開發工程師,2018年3月加入團隊,目前主要負責自營端 H5 項目開發。