Babel 入門指南
?:warning: 注意:
Babel 可以與很多構(gòu)建工具(如
Browserify
搂妻、Grunt
蒙保、Gulp
等)進(jìn)行集成。由于本教程選擇Webpack
叽讳,所以只講解與Webpack
的集成追他。想了解如何與其它工具集成,請(qǐng)參考:官方文檔 - installation
簡(jiǎn)介
Babel
是一個(gè)通用的多用途 JavaScript 編譯器岛蚤。
Babel 能做什么邑狸?
Babel 通過語法轉(zhuǎn)換來支持最新版本的 JavaScript (ES6),而不用等待瀏覽器的支持涤妒。
Babel 可以轉(zhuǎn)換 React 的 JSX 語法和刪除類型注釋单雾。
Babel 是由插件構(gòu)建的。因此她紫,你可以根據(jù)自己的需要訂制硅堆。
支持 source map ,所以您可以輕松調(diào)試您編譯的代碼贿讹。
Babel 不能做什么渐逃?
- Babel 只轉(zhuǎn)換語法(如箭頭函數(shù)),不支持新的全局變量民褂。但是茄菊,您可以使用
babel-polyfill
來輔助支持疯潭。
安裝 Babel
babel-cli
babel-cli
是 Babel 的命令行工具。
安裝
# 本地安裝
$ npm install --save-dev babel-cli
# 全局安裝
$ npm install --global babel-cli
用法
# 將編譯后的結(jié)果直接輸出至終端
$ babel example.js
# 將結(jié)果寫入到指定的文件
$ babel example.js --out-file compiled.js
$ babel example.js -o compiled.js
# 將一個(gè)目錄整個(gè)編譯成一個(gè)新的目錄
$ babel src --out-dir lib
$ babel src -d lib
與 package.json
集成
?:pushpin: 提示:
建議使用本地安裝方式安裝
babel-cli
面殖。原因在與:
- 在同一臺(tái)機(jī)器上的不同項(xiàng)目或許會(huì)依賴不同版本的 Babel 并允許你有選擇的更新竖哩。
- 這意味著你對(duì)工作環(huán)境沒有隱式依賴,這讓你的項(xiàng)目有很好的可移植性并且易于安裝脊僚。
本地安裝 babel-cli
相叁,直接使用 babel
命令將無法識(shí)別。你可以選在在 package.json
文件的 scripts
屬性中定義命令辽幌。npm
會(huì)自動(dòng)找到本地安裝的庫(kù)增淹。
{
"scripts": {
"build": "babel src -d lib"
},
"devDependencies": {
"babel-cli": "^6.0.0"
},
}
現(xiàn)在可以在終端里執(zhí)行命令:
$ npm run build
?:flashlight: 示例DEMO01: (SOURCE)
說明:
示例的上一級(jí)目錄
codes/chapter04/babel
已經(jīng)配好了配置文件。在
codes/chapter04/babel
路徑下執(zhí)行命令:$ npm install $ npm run demo01
會(huì)生成一個(gè)
dist/demo01
目錄乌企,其中就是被轉(zhuǎn)碼后的文件埠通。
babel-node
babel-cli
工具自帶一個(gè) babel-node
命令,提供一個(gè)支持 ES6 的 REPL 環(huán)境逛犹。它支持 Node 的 REPL 環(huán)境的所有功能,而且可以直接運(yùn)行 ES6 代碼梁剔。
它不用單獨(dú)安裝虽画,而是隨 babel-cli
一起安裝。然后荣病,執(zhí)行 babel-node
就進(jìn)入 PEPL 環(huán)境码撰。
然后用 babel-node
來替代 node
運(yùn)行所有的代碼:
$ babel-node
> (x => x * 2)(1)
2
babel-node
命令可以直接運(yùn)行ES6腳本:
$ babel-node example.js
如果用 npm 的話只需要這樣做:
{
"scripts": {
"script-name": "babel-node script.js"
},
"devDependencies": {
"babel-cli": "^6.0.0"
},
}
然后,執(zhí)行命令:
$ npm run babel-node
babel-register
下一個(gè)常用的運(yùn)行 Babel 的方法是通過 babel-register
个盆。這種方法只需要引入文件就可以運(yùn)行 Babel脖岛,或許能更好地融入你的項(xiàng)目設(shè)置。
?:warning: 注意:
這種方法并不適合正式產(chǎn)品環(huán)境使用颊亮。 直接部署用此方式編譯的代碼不是好的做法柴梆。 在部署之前預(yù)先編譯會(huì)更好。
不過用在構(gòu)建腳本或是其他本地運(yùn)行的腳本中是非常合適的终惑。
安裝
$ npm install --save-dev babel-register
使用
- 創(chuàng)建
index.js
文件:
console.log("Hello world!");
這是绍在,使用 node index.js
來運(yùn)行它是不會(huì)使用 Babel 來編譯的。所以我們需要設(shè)置 babel-register
雹有。.
- 創(chuàng)建
register.js
文件:
require("babel-register");
require("./index.js");
這樣做可以把 Babel 注冊(cè)到 Node 的模塊系統(tǒng)中并開始編譯其中 require
的所有文件偿渡。
-
執(zhí)行命令
現(xiàn)在我們可以使用
register.js
來代替node index.js
來運(yùn)行了。
$ node register.js
需要注意的是:你不能在你要編譯的文件內(nèi)同時(shí)注冊(cè) Babel霸奕,因?yàn)?node 會(huì)在 Babel 編譯它之前就將它執(zhí)行了溜宽。
?:flashlight: 示例DEMO02: (SOURCE)
說明:
示例的上一級(jí)目錄
codes/chapter04/babel
已經(jīng)配好了配置文件。在
codes/chapter04/babel
路徑下執(zhí)行命令:$ npm install $ npm run demo02
控制臺(tái)會(huì)打印如下內(nèi)容:
> node demo02/register.js Hello world!
babel-core
如果你需要以編程的方式來使用 Babel质帅,可以使用 babel-core
這個(gè)包适揉。
安裝
$ npm install babel-core
使用
在代碼中引入 babel-core
var babel = require("babel-core");
編譯 API
# 如果是字符串形式的 JavaScript 代碼留攒,可以使用 transform 編譯
babel.transform("code();", options);
// => { code, map, ast }
# 如果是文件的話,異步編譯使用 transformFile
babel.transformFile("filename.js", options, function(err, result) {
result; // => { code, map, ast }
});
# 如果是文件的話涡扼,同步編譯使用 transformFileSync
babel.transformFileSync("filename.js", options);
// => { code, map, ast }
# 要是已經(jīng)有一個(gè) Babel AST(抽象語法樹)了就可以直接從 AST 進(jìn)行轉(zhuǎn)換
babel.transformFromAst(ast, code, options);
// => { code, map, ast }
與 webpack 集成
?:pushpin: 提示:
本教程由于選擇的編譯工具為
webpack
稼跳,所以這里只介紹與webpack
的集成。實(shí)際上吃沪,Babel 還可以與其它許多工具集成汤善,更多內(nèi)容參考:官方文檔 - setup
安裝
$ npm install --save-dev babel-loader babel-core
**配置 **
在 Chapter03 的 Webpack 資源管理 一文中,介紹過使用 babel-loader 來處理 React 語法票彪。
在 webpack.config.js 配置如下:
// 關(guān)于模塊配置
module: {
// 模塊規(guī)則(配置 loader红淡、解析器等選項(xiàng))
rules: [
{
// 語義解釋器,將 js/jsx 文件中的 es2015/react 語法自動(dòng)轉(zhuǎn)為瀏覽器可識(shí)別的 Javascript 語法
test: /\.jsx?$/,
include: path.resolve(__dirname, "app"),
loader: "babel-loader",
},
]
},
?:flashlight: 示例
chapter03-jigsaw: (SOURCE)
chapter04-jigsaw: (SOURCE)
說明:
chapter04-jigsaw
和chapter03-jigsaw
相比降铸,多了一個(gè).babelrc
文件在旱。它其實(shí)是將chapter03-jigsaw
中的webpack.common.js
文件里的 babel-loader 的配置移入了.babelrc
文件。這兩個(gè)代碼目錄的執(zhí)行結(jié)果完全相同推掸。
執(zhí)行方法:
$ npm install # 開發(fā)環(huán)境 - 本地啟動(dòng)一個(gè)訪問地址為 localhost:9000 的 web app $ npm run dev # 開發(fā)環(huán)境 - 生成一個(gè) dist 目錄桶蝎,其中打包了所有資源文件,在瀏覽器打開 index.html谅畅,可以看到和開發(fā)環(huán)境差不多的展示登渣。 $ npm run prod # 清除輸出目錄 dist $ npm run clean
配置 Babel
?:pushpin: 提示:
由于
Babel
是一個(gè)非常靈活的通用編譯器,因此默認(rèn)情況下它反而什么都不做毡泻。你需要通過配置文件胜茧,明確地告訴 Babel 應(yīng)該要做什么。
.babelrc
.babelrc
文件是 Babel
的默認(rèn)配置文件仇味。
.babelrc
文件的內(nèi)容形式就是序列化的 JSON呻顽。
該文件用來設(shè)置轉(zhuǎn)碼規(guī)則(presets)和插件(plugins),基本格式如下:
{
"presets": [],
"plugins": []
}
轉(zhuǎn)碼規(guī)則(preset)
轉(zhuǎn)碼規(guī)則可以告訴 Babel 去處理什么語法丹墨。
常見的轉(zhuǎn)碼規(guī)則有:
-
babel-preset-es2015
這是 ES2015(最新版本的 JavaScript 標(biāo)準(zhǔn)廊遍,也叫做 ES6)的轉(zhuǎn)碼規(guī)則。使用它后贩挣,Babel 可以將 ES6 語法轉(zhuǎn)碼為普通 JavaScript(即 ES5) 語法昧碉。
-
babel-preset-react
這是 React 的轉(zhuǎn)碼規(guī)則。使用它后揽惹,Babel 可以將 React 語法轉(zhuǎn)碼為普通 JavaScript 語法被饿。
-
babel-preset-stage-x
這是 ES7 不同階段語法提案的轉(zhuǎn)碼規(guī)則。使用它后搪搏,Babel 可以將 ES7 不同階段語法轉(zhuǎn)碼為普通 JavaScript 語法狭握。
?:pushpin: 提示:
JavaScript 還有一些提案,正在積極通過 TC39(ECMAScript 標(biāo)準(zhǔn)背后的技術(shù)委員會(huì))的流程成為標(biāo)準(zhǔn)的一部分疯溺。
這個(gè)流程分為 5(0-4)個(gè)階段论颅。 隨著提案得到越多的關(guān)注就越有可能被標(biāo)準(zhǔn)采納哎垦,于是他們就繼續(xù)通過各個(gè)階段,最終在階段 4 被標(biāo)準(zhǔn)正式采納恃疯。以下是4 個(gè)不同階段的(打包的)預(yù)設(shè):
babel-preset-stage-0
babel-preset-stage-1
babel-preset-stage-2
babel-preset-stage-3
stage-4 預(yù)設(shè)是不存在的因?yàn)樗褪巧厦娴?
es2015
預(yù)設(shè)漏设。以上每種預(yù)設(shè)都依賴于緊隨的后期階段預(yù)設(shè)。例如今妄,
babel-preset-stage-1
依賴babel-preset-stage-2
郑口,后者又依賴babel-preset-stage-3
。
安裝
# es2015(即ES6)語法轉(zhuǎn)碼規(guī)則
$ npm install --save-dev babel-preset-es2015
# react 語法轉(zhuǎn)碼規(guī)則
$ npm install --save-dev babel-preset-react
# stage 是指 ES7 不同階段的語法轉(zhuǎn)碼規(guī)則盾鳞,選裝一個(gè)即可
$ npm install --save-dev babel-preset-stage-0
$ npm install --save-dev babel-preset-stage-1
$ npm install --save-dev babel-preset-stage-2
$ npm install --save-dev babel-preset-stage-3
使用
安裝完后犬性,需要在配置文件 .babelrc
中引入項(xiàng)目中實(shí)際需要的預(yù)設(shè)轉(zhuǎn)碼規(guī)則,讓 Babel 得以知道規(guī)則腾仅。
形式如下:
{
"presets": [
"es2015",
"react",
"stage-0"
],
"plugins": []
}
插件(plugins)
插件是 Babel 的核心乒裆。
Babel 插件大致分為三類:
-
轉(zhuǎn)碼插件
有很多種插件:將ES6 / ES2015轉(zhuǎn)換為ES5,轉(zhuǎn)換為ES3推励,minification鹤耍,JSX,flow验辞,實(shí)驗(yàn)功能等等惰蜜。
-
語法插件
這些只是使轉(zhuǎn)碼插件能夠解析某些功能(轉(zhuǎn)碼插件已經(jīng)包含語法插件,因此這兩個(gè)功能你都不需要):
babel-plugin-syntax-x
-
助手
這些主要用于各種插件內(nèi)部使用:
babel-helper-x
受神。
更多插件請(qǐng)?jiān)?npm 搜索(真的好多!)
更詳細(xì)介紹請(qǐng)參考:官方文檔 - 插件
在其它工具中配置
?:pushpin:? 提示:
除了在
.babelrc
文件中定義 Babel 配置格侯。實(shí)際上鼻听,還可以在其他工具中對(duì)其進(jìn)行配置。
在 package.json
中配置
可以在 package.json
文件的 babel
屬性中配置 Babel 規(guī)則联四。
配置方法與 .babelrc
文件完全相同撑碴。
形式如下:
"babel": {
"presets": [
"es2015"
]
"plugins": []
},
在 webpack.config.js
中配置
可以在 webpack.config.js
文件配置 babel-loader
時(shí),直接在 options
屬性中配置 Babel 規(guī)則朝墩。
形式如下:
{
test: /\.jsx?$/,
include: path.resolve(__dirname, "app"),
exclude: /node_modules/,
loader: "babel-loader",
options: {
presets: [
[
"es2015",
{
"modules": false
}
],
"react"
],
plugins: [
"syntax-dynamic-import", // 動(dòng)態(tài)導(dǎo)入插件
"react-hot-loader/babel" // 開啟 React 代碼的模塊熱替換(HMR)
]
},
}
執(zhí)行 Babel 生成的代碼
即便你已經(jīng)用 Babel 編譯了你的代碼醉拓,但這還不算完。
babel-polyfill
Babel 幾乎可以編譯所有新潮的 JavaScript 語法收苏,但對(duì)于 APIs 來說卻并非如此亿卤。
比方說,下列含有箭頭函數(shù)的需要編譯的代碼:
function addAll() {
return Array.from(arguments).reduce((a, b) => a + b);
}
最終會(huì)變成這樣:
function addAll() {
return Array.from(arguments).reduce(function(a, b) {
return a + b;
});
}
然而鹿霸,它依然無法隨處可用排吴。因?yàn)椴⒎撬械?JavaScript 環(huán)境都支持 Array.from
。
為了解決這個(gè)問題懦鼠,我們使用一種叫做 Polyfill(代碼填充钻哩,也可譯作兼容性補(bǔ)兑傺摺) 的技術(shù)。 簡(jiǎn)單地說街氢,polyfill 即是在當(dāng)前運(yùn)行環(huán)境中用來復(fù)制(意指模擬性的復(fù)制扯键,而不是拷貝)尚不存在的原生 api 的代碼。 能讓你提前使用還不可用的 APIs珊肃,Array.from
就是一個(gè)例子荣刑。
Babel 提供了 babel-polyfill
來支持 polyfill 。
安裝
$ npm install --save babel-polyfill
使用
然后近范,只需要在文件頂部導(dǎo)入 babel-polyfill
就可以了:
import "babel-polyfill";
babel-runtime
babel-runtime 與 polyfill 類似嘶摊,不同之處在于它不修改全局范圍,并且與 babel-plugin-transform-runtime
(通常在庫(kù)/插件代碼中)一起使用评矩。
為了實(shí)現(xiàn) ECMAScript 規(guī)范的細(xì)節(jié)叶堆,Babel 會(huì)使用“助手”方法來保持生成代碼的整潔。
由于這些助手方法可能會(huì)特別長(zhǎng)并且會(huì)被添加到每一個(gè)文件的頂部斥杜,因此你可以把它們統(tǒng)一移動(dòng)到一個(gè)單一的“運(yùn)行時(shí)(runtime)”中去虱颗。
通過安裝 babel-plugin-transform-runtime
和 babel-runtime
來開始。
$ npm install --save-dev babel-plugin-transform-runtime
$ npm install --save babel-runtime
然后更新 .babelrc
:
{
"presets": [
"es2015",
"react",
"stage-0"
],
"plugins": [
"transform-runtime",
"transform-es2015-classes"
]
}
現(xiàn)在蔗喂,Babel 會(huì)把這樣的代碼:
class Foo {
method() {}
}
編譯成:
import _classCallCheck from "babel-runtime/helpers/classCallCheck";
import _createClass from "babel-runtime/helpers/createClass";
let Foo = function () {
function Foo() {
_classCallCheck(this, Foo);
}
_createClass(Foo, [{
key: "method",
value: function method() {}
}]);
return Foo;
}();
這樣就不需要把 _classCallCheck
和 _createClass
這兩個(gè)助手方法放進(jìn)每一個(gè)需要的文件里去了忘渔。