我第一次打開搜索引擎查詢關於 Babel 的資料時,出現的居然是關於 Babel 的傳說。後來我花了小一天的時間去了解這個傳說(來自《舊約聖經》)。前端
Babel Tower 是全人類聯手建造的一個建築,人們決心協力修建一座通天高塔。 由於人們內心少了對上帝的敬畏,多了爲本身歌功頌德的功利。上帝不但願這個奇觀建成,因而讓人們分化成不一樣的語言,令其不能交流。以後,由於溝通不順暢,工程被迫放棄,並且人類今後再也不團結,由於語言不通而分化成不一樣部落,並因爲溝通問題,常常發生戰亂,所以再無力撼動上帝的權威。node
瞭解完這個神話以後,我後面就好好的去了解了一些有關 Babel 的知識,下面就是正題。webpack
內容已經發布在 gitHub 了,歡迎圍觀 Star,更多文章都在 gitHub。git
Babel 官方文檔: babeljs.io/github
咱們知道各個瀏覽器對 JavaScript 版本的支持各不相同,有不少優秀的新語法都不能直接在瀏覽器中運行。爲了解決這個「溝通不順暢」的問題,因此就有了 Babel,Babel 的出現使得咱們能夠無須顧忌的去使用 ES6+ 的語法。web
Babel is a JavaScript compiler.json
這也是爲什麼咱們必須使用 ES6+ 語法的前提條件。api
若是你如今還不清楚 ES6+ 語法的話,趕快學習去吧,要否則你就只能回家繼承幾十億的家產啦。瀏覽器
先看下面這張圖: bash
你會發現 ES6 的語法確實被編譯成瀏覽器能夠識別的版本了,你是否是也在問這事怎麼作到的呢?
babel 總共分爲三個階段:解析,轉換,生成。
咱們須要知道如今 babel 自己是不具有這種轉化功能,提供這些轉化功能的是一個個 plugin。因此咱們沒有配置任何 plugin 的時候,通過 Babel 輸出的代碼是沒有改變的。
Babel 自 6.0 起,就再也不對代碼進行轉換。如今只負責圖中的 parse 和 generate 流程,轉換代碼的 transform 過程全都交給插件去作。
例子:
// 模板字面量
const name = '小生方勤';
let hello = `hello ${name}`;
複製代碼
上面是一個簡單的模板字面量的例子,咱們清楚這個是 ES6 的新特性,在不支持 ES6 的運行平臺這段代碼是會報錯的,因此咱們須要 Babel 來將其編譯成 ES5 的代碼。
因此咱們須要以下來配置 babel:
// .babelrc 文件
{
"plugins": [
"transform-es2015-template-literals" // 轉譯模版字符串的 plugins
],
"presets": ["env", "stage-2"]
}
複製代碼
preset(即一組預先設定的插件)
preset: babel 插件集合的預設,包含某些插件 plugin。顯然像上面那樣一個一個配置插件會很是的麻煩,爲了方便,babel 爲咱們提供了一個配置項叫作 persets(預設)。
當前 babel 推薦使用 babel-preset-env 替代 babel-preset-es201X ,env 的支持範圍更廣,包含es201X 的全部語法編譯,而且它能夠根據項目運行平臺的支持狀況自行選擇編譯版本。
列入如下代碼的執行順序爲:
// .babelrc 文件
{
"plugins": [
"transform-es2015-template-literals", // 轉譯模版字符串的 plugins
],
"presets": [
["env", {
// 是否自動引入 polyfill,開啓此選項必須保證已經安裝了 babel-polyfill
// 「usage」 | 「entry」 | false, defaults to false.
"useBuiltIns": "usage"
}], "stage-2"]
}
複製代碼
這裏講一講 useBuiltIns 配置
咱們可能在全局引入 babel-polyfill,這樣打包後的整個文件體積必然是會變大的。
可是經過設置 "useBuiltIns": "usage"
可以把 babel-polyfill 中你須要用到的部分提取出來,不須要的去除。
useBuiltIns 參數說明:
瞭解過 Babel 的同窗,是否也以爲的模塊有點多呢?我開始學習的時候就有這種感受。其實每一個模塊是各司其職的。
這個模塊是最能顧名思義的了,即 babel 的核心模塊。babel 的核心 api 都在這個模塊中。也就是這個模塊會把咱們寫的 js 代碼抽象成 AST 樹;而後再將 plugins 轉譯好的內容解析爲 js 代碼。
具體怎麼工做的這裏就不詳細說了,由於我也不知道。
babel-cli 官方文檔:babeljs.io/docs/en/bab…
babel-cli 是一個經過命令行對 js 文件進行轉換的工具。
固然咱們通常不會使用到這個模塊,由於通常咱們都不會手動去作這個工做,這個工做基本都集成到模塊化管理工具中去了,好比 webpack、Rollup 等。
簡單使用(須要先安裝 babel-cli):
babel test.js -o compiled.js
複製代碼
babel-node 是 babel-cli 的一部分,因此它在安裝 babel-cli 的時候也同時安裝了。
它使 ES6+ 能夠直接運行在 node 環境中。
babel 對一些新的 API 是沒法轉換,好比 Generator、Set、Proxy、Promise 等全局對象,以及新增的一些方法:includes、Array.form 等。因此這個時候就須要一些工具來爲瀏覽器作這個兼容。
官網的定義:babel-polyfill 是爲了模擬一個完整的 ES6+ 環境,旨在用於應用程序而不是庫/工具。
babel-polyfill 主要有兩個缺點:
由於上面兩個問題,因此在 Babel7 中增長了 babel-preset-env,咱們設置 "useBuiltIns": "usage"
這個參數值就能夠實現按需加載 babel-polyfill 啦。
在使用 Babel6 的時候, .babelrc 文件中會使用 babel-plugin-transform-runtime,而 package.json 中的 dependencies 同時包含了 babel-runtime,由於在使用 babel-plugin-transform-runtime 的時候必須把 babel-runtime 當作依賴。
.babelrc 配置:
{
"presets": [
["env"]
],
"plugins": [
["transform-runtime", {
"helpers": false, // defaults to true
"polyfill": false, // defaults to true
"regenerator": true, // defaults to true
"moduleName": "babel-runtime" // defaults to "babel-runtime"
}]
]
}
複製代碼
咱們在啓用插件 babel-plugin-transform-runtime 後,Babel 就會使用 babel-runtime 下的工具函數,將一些瀏覽器不能支持的特性重寫,而後在項目中使用。
babel-runtime 內部也集成了 core-js、 regenerator、helpers 等
因爲採用了沙盒機制,這種作法不會污染全局變量,也不會去修改內建類的原型,因此會有重複引用的問題。
如今最好的實踐應該是在 babel-preset-env 設置 "useBuiltIns": "usage",按需引入 polyfill。
方案 | 優勢 | 缺點 |
---|---|---|
@babel/runtime & @babel/plugin-transform-runtime | 按需引入, 打包體積小 | 不能兼容實例方法 |
@babel/polyfill | 完整模擬 ES2015+ 環境 | 打包體積過大, 污染全局對象和內置的對象原型 |
@babel/preset-env | 按需引入, 可配置性高 | 小生不知 -_- |
淘汰 es201x,刪除 stage-x,推薦 env
若是你還在使用 es201x,官方建議使用 env 進行替換。淘汰並非刪除,只是不推薦使用。
但 stage-x 是直接被刪了,也就是說在 babel7 中使用 es201X 是會報錯的。
babel 7 的一個重大變化,把全部 babel-* 重命名爲 @babel/*,
例如:
babel 7.0 開始再也不支持 nodejs 0.10, 0.12, 4, 5 這四個版本,至關於要求 nodejs >= 6。
還有一些包從其餘包獨立出來的變化等等
接下來我會專門寫一篇關於開發環境配置的問題,也就是本身完成腳手架的功能,因此這裏就不提如何配置 Babel 啦。
若是你想進【大前端交流羣】關注公衆號點擊「交流加羣」添加機器人自動拉你入羣。關注我第一時間接收最新干貨。