babel知識體系漫談

前言

說實在的,前端發展到現在,不用個(webpack|babel|nodeJS|typescript)(可選),

你都不好意思說這個項目具備工程化和多人協作的能力。

關於前端工程化的問題,業界的主流討論點主要集中在組件規範之web-components,

框架引入之react、vue,構建相關之webpack、roollup、gulp,語法相關之ES6/7、typescript等方面。

由於對於現在的前端開發而言,每個討論點都可以講非常多的東西。

為了提高文章的質量,我就主要針對構建相關中的babel來展開討論。

本文關於babel的論述主要分為下面幾塊:

  1. babel編譯體系介紹
  2. babel插件及預設
  3. babel-register在gulp和node項目中的使用
  4. babel的polyfill引入機制
  5. 在babel升級到6時,如何兼容babel5針對ES6/7的編譯方式
  6. babel總結

1.babel編譯體系介紹

1.核心包

//主入口:集成babylon babel-traverse n // babel-generator暴露babel.transform方法來編譯source coden babel-coren //語法字元串解析parsern babylonn //結合plugins和presets(plugins)遍歷AST語法樹n babel-traversen //生成最後的編譯字元串n babel-generatorn

2. 整體的babel編譯大概按照如下流程進行

input stringn -> babylon parsern -> ASTn -> babel-traverse transformer[s] //結合plugins和presets(plugins)遍歷AST語法樹n -> ASTn -> babel-generatorn -> output stringn

可以看到babel插件在生成AST後,會經歷一個plugin和presets的轉換才會到output string, 很多github上開源的babel插件也是基於這個時機個性化自己的一些轉換需求和babel配置的。 接下來我們看下babel的presets和plugins這塊

2.babel插件及預設presets(預置插件方式)

Presets是一個plugin數組來描述對AST進行transform的轉換關係。

在babel6以後的版本,默認內置的transformer都被移除了。

babel官方本身是維護了一些比較常用的babel-preset-es2015等預設plugins。

直觀的解釋Presets的話,可以認為Presets是plugins的一個namespace,引入Presets即相當於引入了plugins,因此可以基本認為插件是babel的核心!!

由於babylon階段已經將源代碼預先為AST樹了,

所以,大部分的插件工作只需要遵循AST tree數據結構的那一套邏輯,即可完成AST節點的個性化。

具體的實踐可以直接查看官方的plugin編寫文檔

3.babel-register在gulp和node項目中的使用

babel-register的設計思想非常厲害,簡單的來說就是require hook。

通過修改require function,對所有的通過require引入的代碼先經過babel編譯一遍,再給到runtime執行。

由於開發者更喜歡用ES6/7的語法來寫代碼,因此babel-register在nodejs環境下越來越得到各大技術宗派的喜愛。

比如gulp4的插件編寫就內置了babel-register,koa2也推崇採用babel-register來編譯用ES6/7寫成的代碼。

4.babel的polyfill引入機制

babel的polyfill這塊是基於core-js的,像類似Promise對象、Array.includes等ES6/7方法,都可以在core-js中找到實現。

所以我的個人建議是按需引入core-js的模塊而不是整個babel-polyfill bundle,來對ES6/7新增的數據對象和方法做polyfill。

5.在babel升級到6時,如何兼容babel5針對ES6/7的編譯方式

好吧,關於babel5 babel6社區確實有很多吐槽,主要有如下幾個改動的點。

  1. 本來babel5的大鍋飯配置模式變成了babel6的按需添加插件的形式。

  2. 本來babel5對export default的輸出形式在babel6下會出現default關鍵字。

由於以上兩點的存在,導致很多基於babel5的項目升級成babel6後存在不兼容的情況。

其實,在了解了babel的compile system後,以上的兩個問題是很容易解決的。

比如babel-plugin-add-module-exports這個庫就可以完美解決export default 問題。

比如我寫的babel-preset-es2015-ie8即集成了關鍵字過濾從而解決IE8項目的集成。

最後,對於沒有特殊要求的前端項目而言,我的建議是直接寫個.babelrc來配置babel的編譯方式。

babel總結

babel的出現讓開發者可以自由的採用ES6/7的語法來編寫JS項目,極大的豐富了開發層面的JS語言特性。

babel的AST parser、polyfill、 register一起完成了babel體系對JS的完備解決方案。

關於babel更多的知識,大家如果有興趣的話直接參考babel的handbook。

本文首發於作者的github blog。

關於webpack等的文章可以戳這裡webpack編譯流程漫談

參考資料

plugin-handbookuser-guide


推薦閱讀:

thunk
[一勺燴]CSS3中常用字體圖標庫總結
TypeScript 2.5~2.6 新特性一覽
2017 年 4 月:前端與設計資源集
(譯)關於響應式的另一種思考

TAG:前端开发 | webpack | Nodejs |