babel知識體系漫談
前言
說實在的,前端發展到現在,不用個(webpack|babel|nodeJS|typescript)(可選),
你都不好意思說這個項目具備工程化和多人協作的能力。
關於前端工程化的問題,業界的主流討論點主要集中在組件規範之web-components,
框架引入之react、vue,構建相關之webpack、roollup、gulp,語法相關之ES6/7、typescript等方面。
由於對於現在的前端開發而言,每個討論點都可以講非常多的東西。
為了提高文章的質量,我就主要針對構建相關中的babel來展開討論。
本文關於babel的論述主要分為下面幾塊:
- babel編譯體系介紹
- babel插件及預設
- babel-register在gulp和node項目中的使用
- babel的polyfill引入機制
- 在babel升級到6時,如何兼容babel5針對ES6/7的編譯方式
- 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社區確實有很多吐槽,主要有如下幾個改動的點。
本來babel5的大鍋飯配置模式變成了babel6的按需添加插件的形式。
本來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 月:前端與設計資源集
※(譯)關於響應式的另一種思考