babel 外掛開發案例

銅板街技術發表於2019-01-30

寫在前面

本文將以把es6的語法let改為var為例,講述如何編寫一個babel外掛。其中涉及到一些babel的基本知識,babel的工作流程,語法抽象樹等。

babel簡介

關於babel 官網做了如下解釋:

Babel 是一個工具鏈,主要用於在舊的瀏覽器或環境中將 ECMAScript 2015+ 程式碼轉換為向後相容版本的 JavaScript 程式碼

相信大家在開發中或多或少的都使用過bable對程式碼進行編譯。在babel配置檔案.babelrc中最主要就是對presetsPlugins的配置。其中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的工作過程

image

  • 解析,解析步驟接收程式碼並輸出 AST。
  • 轉換,轉換步驟接收AST並對其進行遍歷,在此過程中對節點進行新增、更新及移除等操作
  • 生成,程式碼生成步驟把最終(經過一系列轉換之後)的 AST 轉換成字串形式的程式碼,同時還會建立原始碼對映(source maps)。

其中,解析、生成階段由Babel核心完成,而轉換階段,則由Babel外掛完成,這也是本文的重點。

抽象語法樹(AST)

在電腦科學中,抽象語法樹(Abstract Syntax Tree,AST),或簡稱語法樹(Syntax tree),是原始碼語法結構的一種抽象表示。它以樹狀的形式表現程式語言的語法結構,樹上的每個節點都表示原始碼中的一種結構。之所以說語法是“抽象”的,是因為這裡的語法並不會表示出真實語法中出現的每個細節。

開發一個babel外掛一定要對AST有所瞭解,上面是維基百科對抽象語法樹的解釋

舉個例子:

var a = 1;
複製程式碼

轉換成的AST結構為:

babel 外掛開發案例

babel 外掛開發案例

這裡是可以實時檢視程式碼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 外掛開發案例

babel 外掛開發案例

總結

本文演示的只是一個簡單的babel外掛的開發,我們在轉換的過程中拿到程式碼的AST結構後,就可以隨心所欲的對程式碼進行增加、刪除、修改。我們還可以通過編寫babel外掛實現更多的功能,比如刪除程式碼中所有console.log等。

作者簡介

卓月,銅板街前端開發工程師,2018年3月加入團隊,目前主要負責自營端 H5 專案開發。

babel 外掛開發案例

更多精彩內容,請掃碼關注 “銅板街技術” 微信公眾號。

相關文章