寫在前面
本文將以把es6的語法let
改為var
為例,講述如何編寫一個babel外掛。其中涉及到一些babel的基本知識,babel的工作流程,語法抽象樹等。
babel簡介
關於babel 官網做了如下解釋:
Babel 是一個工具鏈,主要用於在舊的瀏覽器或環境中將 ECMAScript 2015+ 程式碼轉換為向後相容版本的 JavaScript 程式碼
相信大家在開發中或多或少的都使用過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新增的箭頭函式。
所以在我們的日常開發中也可以根據自己的需求開發bebal外掛,從而提高開發效率。
babel的編譯過程
Babel轉碼的過程分三個階段:解析(parse)、轉換(transform)、生成(generate)。下面這張圖可以很好的說明babel的工作過程
- 解析,解析步驟接收程式碼並輸出 AST。
- 轉換,轉換步驟接收AST並對其進行遍歷,在此過程中對節點進行新增、更新及移除等操作
- 生成,程式碼生成步驟把最終(經過一系列轉換之後)的 AST 轉換成字串形式的程式碼,同時還會建立原始碼對映(source maps)。
其中,解析、生成階段由Babel核心完成,而轉換階段,則由Babel外掛完成,這也是本文的重點。
抽象語法樹(AST)
在電腦科學中,抽象語法樹(Abstract Syntax Tree,AST),或簡稱語法樹(Syntax tree),是原始碼語法結構的一種抽象表示。它以樹狀的形式表現程式語言的語法結構,樹上的每個節點都表示原始碼中的一種結構。之所以說語法是“抽象”的,是因為這裡的語法並不會表示出真實語法中出現的每個細節。
開發一個babel外掛一定要對AST有所瞭解,上面是維基百科對抽象語法樹的解釋
舉個例子:
var a = 1;
複製程式碼
轉換成的AST結構為:
這裡是可以實時檢視程式碼ast結構的網站astexplorer.net/,有助於更好的瞭解ast以及編寫babel外掛
開發babel外掛
安裝@babel/cli,@babel/core
可用於從命令列編譯檔案
"@babel/cli": "^7.1.5",
"@babel/core": "^7.1.6",
複製程式碼
新建js檔案
新建一個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 專案開發。