什麼是Babel
-
什麼是Babel?
- Babel 是我們知道的將 ES6、ES7等程式碼轉譯為 ES5 程式碼且能安全穩定執行最好的工具
- 同時它允許開發者開發外掛, 能夠在編譯時期轉換 JavaScript 的結構。
Babel概述:
-
我們需要知道3個Babel處理流程中的重要工具;
- 解析
- Babylon是一個解析器,它可以將javascript字串,轉化為更加友好的表現形式,稱之為抽象語法樹;
- 在解析過程中有兩個階段:詞法分析和語法分析,
- 詞法分析階段:字串形式的程式碼轉換為令牌(tokens)流,令牌類似於AST中的節點;
- 語法分析階段:把一個令牌流轉化為AST的形式,同時這個階段會把令牌中的資訊轉化為AST的表述結構
- 轉換
- babel-traverse 模組允許你瀏覽、分析和修改抽象語法樹(AST Abstract Syntax Tree)
- Babel接收解析得到的AST並通過babel-traverse對其進行深度優先遍歷,在此過程中對節點進行新增、更新及移除操作。
- babel-traverse 模組允許你瀏覽、分析和修改抽象語法樹(AST Abstract Syntax Tree)
- 生成
- babel-generator 模組用來將轉換後的抽象語法樹(AST Abstract Syntax Tree)轉化為Javascript 字串
- 將經過轉換的AST通過babel-generator再轉換為js程式碼,過程及時深度遍歷整個AST,然後構建轉換後的程式碼字串。
- babel-generator 模組用來將轉換後的抽象語法樹(AST Abstract Syntax Tree)轉化為Javascript 字串
- 解析
Babel 中重要的物件Vistor
babel在處理一個節點時,是以訪問者的形式獲取節點的資訊,並進行相關的操作,這種操作是通過visitor物件實現的。
複製程式碼
在visitor中定義了處理不同節點的函式。
visitor: {
Program: {
enter(path, state) {
console.log('start processing this module...');
},
exit(path, state) {
console.log('end processing this module!');
}
},
ImportDeclaration:{
enter(path, state) {
console.log('start processing ImportDeclaration...');
// do something
},
exit(path, state) {
console.log('end processing ImportDeclaration!');
// do something
}
}
}
複製程式碼
什麼是AST
-
什麼是AST?
- AST (Abstract Syntax Tree)是抽象語法樹英文的縮寫,AST語法樹每一層都擁有相同的結構,這樣的每一層結構也被叫做節點(Node)。
- AST 是原始碼的抽象語法結構樹狀表現形式,Webpack、ESLint、JSX、TypeScript 的編譯和模組化規則之間的轉化都是通過 AST 來實現對程式碼的檢查、分析以及編譯等操作。
- 一個 AST 可以由單一的節點或是成百上千個節點構成。 它們組合在一起可以描述用於靜態分析的程式語法。
-
Javascript 語法的AST(抽象語法樹)
- javascript 語句要想知道抽象語法樹之後的程式碼是什麼,裡面的欄位都代表什麼含義以及遍歷的規則,可以通過javascript語法轉換AST工具來實現javascript語法的線上轉換; 例如:
-
esprima、estraverse 和 escodegen 模組是操作 AST 的三個重要模組,也是實現 babel 的核心依賴。
-
例如:語法轉換外掛需要藉助 babel-core 和 babel-types 兩個模組,就是依賴 esprima、estraverse 和 escodegen
-
轉換的抽象語法樹:
每一個含有type屬性的物件,我們稱之為節點,修改是指獲取對應的型別並修改改節點的屬性即可;
{ "type": "Program", "body": [ { "type": "VariableDeclaration", "declarations": [ { "type": "VariableDeclarator", "id": { "type": "Identifier", "name": "answer" }, "init": { "type": "BinaryExpression", "operator": "*", "left": { "type": "Literal", "value": 6, "raw": "6" }, "right": { "type": "Literal", "value": 7, "raw": "7" } } } ], "kind": "var" } ], "sourceType": "script" 複製程式碼
}
-
estraverse 遍歷和修改AST
-
檢視遍歷過程:
const esprima = require("esprima"); const estraverse = require("estraverse"); let code = "var answer=6 * 7"; // 遍歷語法樹 estraverse.traverse(esprima.parseScript(code), { enter(node) { console.log("enter", node.type); }, leave(node) { console.log("leave", node.type); } }); 複製程式碼
-
列印結果如下:
-
-
以上程式碼通過estraverse模組的traverse方法,將esprima模組裝換的AST進行了遍歷。
-
通過列印type屬性,可以知道深度遍歷AST就是遍歷每一層的type屬性,所以遍歷會分為兩個階段,進入階段和離開階段,在traverse方法中分別用引數enter和leave兩個函式監聽;
-
escodegen 將 AST 轉換成 JS
const esprima = require("esprima");
const estraverse = require("estraverse");
const escodegen= require("escodegen");
let code = "var answer=6 * 7";
let tree=esprima.parseScript(code); // 生成語法樹
// 遍歷語法樹
estraverse.traverse(tree, {
enter(node) {
console.log("enter", node.type);
// 修改變數名
if(node.type==='VariableDeclarator'){
node.id.name='result';
}
},
leave(node) {
console.log("leave", node.type);
}
});
// 編譯修改後的語法樹;
let compileTreeJS=escodegen.generate(tree);
console.log(compileTreeJS);
複製程式碼
- 列印結果如下 :
- var result=6*7
通過工具瞭解抽象語法樹在 JavaScript 中的體現以及在 NodeJS 中用於生成、遍歷和修改 AST 抽象語法樹的核心依賴;讓我們有了更加深刻地認識;