我個人正在寫Node.js的系列學習筆記node-learning-manual,包含了Node.js的基本模組和工程化相關的知識, 如果對你有幫助,請點個start,您的支援是對我最大的鼓勵。
前言
前端發展到現在,可謂是混亂至極,已經遠遠超出我對前端所謂一把jQuery抄起來就是懟,
Webpack, babel, node.js, react, vue各種工程框架,構建工具你不會點好像都不算是個合格的
前端工程師,語法相關的ES6/7總是繞不過Babel,這篇文章就是直接討論Babel。
本文只要圍繞以下幾塊來說:
- Babel編譯過程介紹
- Babel外掛及預設
- Babel-register在專案中的使用
- babel的polyfill引入機制
- babel在前端工程的定位
Babel編譯過程介紹
-
核心包
// 暴露babel.transform方法來編譯source code babel-core // 語法字串解析parser babylon // 結合plugins遍歷AST語法樹 babel-traverse // 生成最後的編譯字串 babel-generator 複製程式碼
-
babel編譯流程
input string -> babylon parser -> AST -> babel-traverse //使用plugins遍歷AST語法樹 -> AST -> babel-generator -> output string 複製程式碼
Babel是一個JavaScrpit的編譯器,從巨集觀的角度來看,它有三個執行階段:解析,轉化,生成。基本上如果不設定配置檔案.babelrc,Babel執行的結果便是 const babel = code => code ,通過讀取程式碼,最後生成一樣的程式碼。Babel的最核心的概念便是外掛,通過在配置檔案 .babelrc中新增不同的外掛基本可以做所有的事情。
Babel外掛(plugins)及預設(presets)
首先聊聊外掛與預設的關係,官方預設便是由官方評審維護的一系列外掛組合。外掛與預設的關係便是父子集合的關係。
每年babel都會評估當年的外掛,babel-preset-env 取代了 es2015, es2016, es2017 以及最新的程式碼
Babel-register在專案中的使用
babel-register的設計思想非常厲害,簡單的來說就是require hook。也是babel常見的一種使用方法。
這種方法只需要引入檔案就可以執行 Babel,或許能更好地融入你的專案設定。
讓我們先在專案中建立index.js檔案
// index.js
console.log("hello world");
複製程式碼
接著需要我們安裝babel-register
$ npm install i -D babel-register
複製程式碼
接著,在專案中建立 register.js
檔案並新增如下程式碼:
require("babel-register");
require("./index.js");
複製程式碼
然後我們只需要啟動 node register.js 便可,通過修改require function,對所有的通過require引入的程式碼先經過babel編譯一遍,再給到runtime執行。
babel的polyfill引入機制
Babel 幾乎可以編譯所有時新的 JavaScript 語法,但對於 APIs 來說卻並非如此。
比方說,下列含有箭頭函式的需要編譯的程式碼:
function addAll() {
return Array.from(arguments).reduce((a, b) => a + b);
}
複製程式碼
最終會變成這樣
function addAll() {
return Array.from(arguments).reduce(function(a, b) {
return a + b;
});
}
複製程式碼
然而,它依然無法隨處可用因為不是所有的 JavaScript 環境都支援 Array.from
。
為了解決這個問題,我們使用一種叫做 Polyfill(程式碼填充,也可譯作相容性補丁) 的技術。 簡單地說,polyfill 即是在當前執行環境中用來複制(意指模擬性的複製,而不是拷貝)尚不存在的原生 api 的程式碼。 能讓你提前使用還不可用的 APIs,Array.from
就是一個例子。
要使用 Babel polyfill,首先用 npm 安裝它:
$ npm install --save babel-polyfill
複製程式碼
然後只需要在檔案頂部匯入 polyfill 就可以了:
import "babel-polyfill";
複製程式碼
所以我的個人建議是按需引入core-js的模組而不是整個babel-polyfill bundle,來對ES6/7新增的資料物件和方法做polyfill。
babel-runtime引入機制
為了實現 ECMAScript 規範的細節,Babel 會使用“助手”方法來保持生成程式碼的整潔。
由於這些助手方法可能會特別長並且會被新增到每一個檔案的頂部,因此你可以把它們統一移動到一個單一的“執行時(runtime)”中去。
通過安裝 babel-plugin-transform-runtime
和 babel-runtime
來開始。
$ npm install --save-dev babel-plugin-transform-runtime
$ npm install --save babel-runtime
複製程式碼
然後更新 .babelrc
:
{
"plugins": [
+ "transform-runtime",
"transform-es2015-classes"
]
}
複製程式碼
現在,Babel 會把這樣的程式碼:
class Foo {
method() {}
}
複製程式碼
編譯成:
import _classCallCheck from "babel-runtime/helpers/classCallCheck";
import _createClass from "babel-runtime/helpers/createClass";
let Foo = function () {
function Foo() {
_classCallCheck(this, Foo);
}
_createClass(Foo, [{
key: "method",
value: function method() {}
}]);
return Foo;
}();
複製程式碼
這樣就不需要把 _classCallCheck
和 _createClass
這兩個助手方法放進每一個需要的檔案裡去了。
babel總結
babel的出現讓開發者可以自由的採用ES6/7的語法來編寫JS專案,極大的豐富了開發 (browser, node) 層面的JS語言特性。
babel的AST parser、polyfill、 register一起完成了babel體系對JS的完備解決方案。
參考資料
我個人正在寫Node.js的系列學習筆記node-learning-manual,包含了Node.js的基本模組和工程化相關的知識, 如果對你有幫助,請點個start,您的支援是對我最大的鼓勵。