Babel介紹

每次ECMAScript新標準出來時,看著酷炫的語法卻礙於瀏覽器支援問題而怯步的我,在知道了Babel這個工具可以將最先進的語法轉為每個瀏覽器都通用的舊語法時,真的是像看到救世主一樣,感動的說不出話來。

Babel是一個可以將工程師所撰寫的程式經由載入的Plugins來轉換為目標語法,也可以用Polyfill來使我們可以用新的globals(ex: Promise)。

安裝

Babel的安裝方式有很多種,在專案中一般會使用像是Webpack這樣的bundler工具引入Babel,但會牽扯到Webpack的設置,本文想聚焦在Babel的概念上,所以使用CLI來做安裝。

  • 建立package.json,本文只是練習用法,直接使用預設的設定
1
npm init -y
  • 安裝babel-cli
1
npm install --save-dev babel-cli
  • 新增src資料夾,在裡面撰寫index.js
1
const helloFunc = (input) => { console.log(`Hello ${input}`)};

這個例子裡用到三個ES2015的語法: constarrow functiontemplate string,本文將以這三個語法來展示Babel的轉換功能。

  • package.json中新增build指令
1
2
3
4
"scripts": {
"build": "babel src -d dist"
...
},
  • 執行build指令
1
npm run build

執行後會看到dist的資料夾,裡面有一個index.js的檔案,開起來會發現跟原本src中的index.js程式碼相同,並沒有經過轉換,這是為什麼呢?

Plugins

BABEL執行時有三個步驟: parsingtransforminggeneration

上一節的例子中執行babel的指令時也經過這三個步驟,而沒有轉換的原因就是出在第二步的transformingBABEL的轉換步驟是仰賴各個plugins提供轉換能力,我們的程式中沒有載入任何的Plugins,所以轉換時並不會做任何事情,現在我們來加入各個語法的Plugins

  • 載入Plugins
1
2
3
npm install --save-dev babel-plugin-transform-es2015-arrow-functions
npm install --save-dev babel-plugin-transform-es2015-block-scoping
npm install --save-dev babel-plugin-transform-es2015-template-literals

上面這三個Plugins分別處理程式碼中的三個語法特性arrow functionconsttemplate string

  • 修改build指令
1
2
3
4
"scripts": {
"build": "babel src -d dist --plugins=transform-es2015-block-scoping,transform-es2015-arrow-functions,transform-es2015-template-literals"
...
},

--plugins參數設置要使用的plugins

  • 執行build指令

執行之後我們會在dist中的index.js中看到轉換的結果。

1
2
3
var helloFunc = function (input) {
console.log("Hello " + input);
};

可以看到我們的程式碼已經被轉為ES5的語法了。

.babelrc

各位不知道是否注意到,在加入了Plugins後,指令變得很長,這還只是設置了三個Plugins的情況,如果之後要設置更多的Plugins那我們的設置會變得相當的困難,所幸BABEL有提供config檔的功能,我們可以將設定全部放到設定檔中。

  • 於根目錄中(跟package.json同個資料夾)建立.babelrc
1
2
3
4
5
6
7
{
"plugins": [
"transform-es2015-arrow-functions",
"transform-es2015-block-scoping",
"transform-es2015-template-literals"
]
}

這邊我們設置plugins的載入。

  • 刪除指令中的--plugins
1
2
3
4
"scripts": {
"build": "babel src -d dist"
...
},

存檔執行後我們一樣可以得到轉換為ES5的程式碼。

Presets

使用Plugins對Babel做設置時,每次要轉換一種語法就必須要載入一種Plugins,每次的設置都是一個麻煩,而且有新的ECMAScript標準釋出,就要自己手動再加入,真的很不方便,為此Babel提供了Presets的設置方式,載入特定目標的Preset時會將相關的Plugins都包含進來,使得載入一個Preset就可以使用整組語法轉換的Plugins。

Babel目前提供三個Presets:

  • env: 依據開發者目標環境的需求做轉換。
  • react: React相關(JSX)的轉換。
  • flow: Flow相關的轉換。

env

env的轉換是為了可以在目標的環境(Browsers或是Node.js)順利地使用較新的語法,例如我們可以直接在專案下撰寫ES2017的語法,在經由env中載入的Plugins做轉換。

查看包含的Plugins

我們可以在plugin-features.js中找到env中所包含的Plugins

使用方式

  • 安裝envpreset
1
npm install --save-dev babel-preset-env
  • 設置.babelrc
1
2
3
{
"presets": ["env"]
}

這樣的設置啟用了env預設的設定,會將所有ES2015ES2016ES2017相關的語法做轉換。

npm run build的指令後我們可以得到轉換為ES5後的程式碼。

指定轉換後的目標環境

env也可以指定專案所需支援的環境來做轉換,如果你只要支援Chrome或是Firefox這類的現代化瀏覽器,由於這些瀏覽器已經支援大部分的ES2015語法,所以就可以使用較少的Plugins來做轉換,節省花費。

env中可以設置node或是browsers的環境目標。

瀏覽器環境

指定瀏覽器環境的方式是使用browserslist,它是使用查詢字串來設定目標瀏覽器。

例如我們只想要支援最新的Chrome,我們可以在.babelrc中做下面的設定:

1
2
3
4
5
6
7
8
9
10
11
{
"presets": [
[
"env", {
"targets": {
"browsers": ["last 1 Chrome versions"]
}
}
]
]
}

這樣我們得到的執行結果就不會經過Plugins的轉換,因為Chrome的最新版本已經支援這些語法了。

註: 可以由browserl.ist來檢查是否查詢語法符合自己的環境。

結語

本文透過實作的方式來講解Babel的使用方式,雖然講的不深,但對於剛學習Babel的人應該會有幫助,希望可以給剛入門的人少走一些歪路。

範例程式

簡報

參考