babel的定義
Babel 是 JavaScript 編譯器,更確切地說是原始碼到原始碼的編譯器,通常也叫做“轉換編譯器(transpiler)”。
babel-core
如果你需要以程式設計的方式來使用 Babel,可以使用 babel-core 這個包
npm install babel-core
var babel = require("babel-core");
字串形式的 JavaScript 程式碼可以直接使用 babel.transform 來編譯
babel.transform("code();....", options);
// => { code, map, ast }
如果是檔案的話,可以使用非同步 api
babel.transformFile("./myCode.js", options, function(err, result) {
result; // => { code, map, ast }
});
對於上述所有方法,options 指的都是http://babeljs.io/docs/usage/…
在options中可以設定presets和plugins,或者建立.babelrc檔案,options預設開啟讀取babelrc檔案的功能。以下是開啟自定義預設和外掛的例子:
const {transform,generate}=require(`babel-core`);
const myPlugin=require(`./myPlugin`);
const mypreset=require(`./mypreset`);
const code = `d = a + b + c`;
var es5Code = transform(code, {
plugins: [myPlugin],
presets: [mypreset]
})
console.log(es5Code.code);
.babelrc
在我們告訴 Babel 該做什麼之前,我們需要建立一個配置檔案。你需要做的就是在專案的根路徑下建立 .babelrc 檔案。然後輸入以下內容作為開始:
{
"presets": [],
"plugins": []
}
由於babelrc的功能預設被開啟,可在options中設定{babelrc:false}來顯式關閉。
presets
預設,包含一系列外掛的集合。目前常用的presets包括es201x,stage-x,env,latest,react,flow。目前羅列的只是babel6的情況。
1. es2015
check-es2015-constants
transform-es2015-arrow-functions
transform-es2015-block-scoped-functions
transform-es2015-block-scoping
transform-es2015-classes
transform-es2015-computed-properties
transform-es2015-destructuring
transform-es2015-duplicate-keys
transform-es2015-for-of
transform-es2015-function-name
transform-es2015-literals
transform-es2015-modules-commonjs
transform-es2015-object-super
transform-es2015-parameters
transform-es2015-shorthand-properties
transform-es2015-spread
transform-es2015-sticky-regex
transform-es2015-template-literals
transform-es2015-typeof-symbol
transform-es2015-unicode-regex
transform-regenerator
2. es2016
transform-exponentiation-operator
3. es2017
syntax-trailing-function-commas
transform-async-to-generator
es201x系列中,只羅列了當年ECMAScript公佈的新特性中的語法部分,至於新特性中的API則全部在polyfill中。
babel-preset-stage-x
JavaScript 還有一些提案,正在積極通過 TC39(ECMAScript 標準背後的技術委員會)的流程成為標準的一部分。
這個流程分為 5(0-4)個階段。 隨著提案得到越多的關注就越有可能被標準採納,於是他們就繼續通過各個階段,最終在階段 4 被標準正式採納。
以下是5 個不同階段的(打包的)預設:
- babel-preset-stage-0 僅僅是個想法
- babel-preset-stage-1 提議
- babel-preset-stage-2 草案
- babel-preset-stage-3 候選
- babel-preset-stage-4 已完成
以上每種預設都依賴於緊隨的後期階段預設。例如,babel-preset-stage-0 包含了 babel-preset-stage-1 babel-preset-stage-2 babel-preset-stage-3。
stage預設是一個一直變化的外掛集合,根據當年釋出的標準內容,動態改變stage的外掛內容,stage3中的候選外掛很可能被完成,那就會在babel新release的版本中去除,而stage2中的草案就會進入到stage3中的候選名單中,像是一個傳接棒的過程,當然草案或者候選的名單隨時可能會被取消。
其中stage-0的do語法糖可以很好的用在jsx中,我們在開發recat的jsx條件判斷程式碼時,可以有以下幾種方式:
1.第一種三元表示式
{condition1?condition2?result1:result2:result3}
2.第二種自執行函式
{(()=>{
if(a){
return ...;
}else{
return ...;
}
})()}
3.第三種do
{
do{
if(a){
`result1`
}else{
`result2`
}
}
}
babel-preset-env
{
"presets": [
["env", {
"targets": {
"browsers": ["last 2 versions", "safari >= 7"]
}
}]
]
}
當env的配置只簡單配置為{presets:[`env`]}時,與babel-preset-latest(官方已不推薦使用)等價,相當於同時集合了三個babel-preset-es201x預設。
env的執行過程是,首先讀取browsers配置中的條件,根據這些條件從browserslist模組可得出該條件下的所有瀏覽器最低版本號列表,而env又為babel的轉譯外掛提供了瀏覽器的最低版本號列表,兩個瀏覽器版本號列表的查詢可得出一個babel轉譯外掛的集合。
browserslist根據條件查出的瀏覽器及版本號:
1%, Last 2 versions => {ie:10,chrome:56...}
env提供的轉譯外掛對應瀏覽器版本號列表:
{
"check-es2015-constants": {
"chrome": "49",
"edge": "14",
"firefox": "51",
"safari": "10",
"node": "6",
"ios": "10",
"opera": "36",
"electron": "1"
},
"transform-es2015-arrow-functions": {
"chrome": "47",
"edge": "13",
"firefox": "45",
"safari": "10",
"node": "6",
"ios": "10",
"opera": "34",
"electron": "0.36"
}....
最後得出結果
{
plugins:[babel外掛1,babel外掛2...]
}
babel墊片
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。
babel墊片有三種:
- babel-runtime
- babel-plugin-transform-runtime
- babel-polyfill
babel-runtime和 babel-plugin-transform-runtime的區別是,相當一前者是手動擋而後者是自動擋,每當要轉譯一個api時都要手動加上require(`babel-runtime`),而babel-plugin-transform-runtime會由工具自動新增,主要的功能是為api提供沙箱的墊片方案,不會汙染全域性的api,因此適合用在第三方的開發產品中。
babel-polyfill則是通過改寫全域性prototype的方式實現,比較適合單獨執行的專案。開啟babel-polyfill的方式,可以直接在程式碼中require,或者在webpack的entry中新增,也可以在babel的env中設定useBuildins為true來開啟。