Babel 入門指南

?:warning: 注意:
Babel 可以與很多構建工具(如
Browserify
、Grunt
、Gulp
等)進行集成。由于本教程選擇Webpack
,所以只講解與Webpack
的集成。想了解如何與其它工具集成,請參考:官方文檔 - installation
簡介
Babel
是一個通用的多用途 JavaScript 編譯器。
Babel 能做什么?
Babel 通過語法轉換來支持最新版本的 JavaScript (ES6),而不用等待瀏覽器的支持。
Babel 可以轉換 React 的 JSX 語法和刪除類型注釋。
Babel 是由插件構建的。因此,你可以根據自己的需要訂制。
支持 source map ,所以您可以輕松調試您編譯的代碼。
Babel 不能做什么?
- Babel 只轉換語法(如箭頭函數),不支持新的全局變量。但是,您可以使用
babel-polyfill
來輔助支持。
安裝 Babel
babel-cli
babel-cli
是 Babel 的命令行工具。
安裝
# 本地安裝
$ npm install --save-dev babel-cli
# 全局安裝
$ npm install --global babel-cli
用法
# 將編譯后的結果直接輸出至終端
$ babel example.js
# 將結果寫入到指定的文件
$ babel example.js --out-file compiled.js
$ babel example.js -o compiled.js
# 將一個目錄整個編譯成一個新的目錄
$ babel src --out-dir lib
$ babel src -d lib
與 package.json
集成
?:pushpin: 提示:
建議使用本地安裝方式安裝
babel-cli
。原因在與:
- 在同一臺機器上的不同項目或許會依賴不同版本的 Babel 并允許你有選擇的更新。
- 這意味著你對工作環境沒有隱式依賴,這讓你的項目有很好的可移植性并且易于安裝。
本地安裝 babel-cli
,直接使用 babel
命令將無法識別。你可以選在在 package.json
文件的 scripts
屬性中定義命令。npm
會自動找到本地安裝的庫。
{
"scripts": {
"build": "babel src -d lib"
},
"devDependencies": {
"babel-cli": "^6.0.0"
},
}
現在可以在終端里執行命令:
$ npm run build
?:flashlight: 示例DEMO01: (SOURCE)
說明:
示例的上一級目錄
codes/chapter04/babel
已經配好了配置文件。在
codes/chapter04/babel
路徑下執行命令:$ npm install $ npm run demo01
會生成一個
dist/demo01
目錄,其中就是被轉碼后的文件。
babel-node
babel-cli
工具自帶一個 babel-node
命令,提供一個支持 ES6 的 REPL 環境。它支持 Node 的 REPL 環境的所有功能,而且可以直接運行 ES6 代碼。
它不用單獨安裝,而是隨 babel-cli
一起安裝。然后,執行 babel-node
就進入 PEPL 環境。
然后用 babel-node
來替代 node
運行所有的代碼:
$ babel-node
> (x => x * 2)(1)
2
babel-node
命令可以直接運行ES6腳本:
$ babel-node example.js
如果用 npm 的話只需要這樣做:
{
"scripts": {
"script-name": "babel-node script.js"
},
"devDependencies": {
"babel-cli": "^6.0.0"
},
}
然后,執行命令:
$ npm run babel-node
babel-register
下一個常用的運行 Babel 的方法是通過 babel-register
。這種方法只需要引入文件就可以運行 Babel,或許能更好地融入你的項目設置。
?:warning: 注意:
這種方法并不適合正式產品環境使用。 直接部署用此方式編譯的代碼不是好的做法。 在部署之前預先編譯會更好。
不過用在構建腳本或是其他本地運行的腳本中是非常合適的。
安裝
$ npm install --save-dev babel-register
使用
- 創建
index.js
文件:
console.log("Hello world!");
這是,使用 node index.js
來運行它是不會使用 Babel 來編譯的。所以我們需要設置 babel-register
。.
- 創建
register.js
文件:
require("babel-register");
require("./index.js");
這樣做可以把 Babel 注冊到 Node 的模塊系統中并開始編譯其中 require
的所有文件。
-
執行命令
現在我們可以使用
register.js
來代替node index.js
來運行了。
$ node register.js
需要注意的是:你不能在你要編譯的文件內同時注冊 Babel,因為 node 會在 Babel 編譯它之前就將它執行了。
?:flashlight: 示例DEMO02: (SOURCE)
說明:
示例的上一級目錄
codes/chapter04/babel
已經配好了配置文件。在
codes/chapter04/babel
路徑下執行命令:$ npm install $ npm run demo02
控制臺會打印如下內容:
> node demo02/register.js Hello world!
babel-core
如果你需要以編程的方式來使用 Babel,可以使用 babel-core
這個包。
安裝
$ 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 }
# 要是已經有一個 Babel AST(抽象語法樹)了就可以直接從 AST 進行轉換
babel.transformFromAst(ast, code, options);
// => { code, map, ast }
與 webpack 集成
?:pushpin: 提示:
本教程由于選擇的編譯工具為
webpack
,所以這里只介紹與webpack
的集成。實際上,Babel 還可以與其它許多工具集成,更多內容參考:官方文檔 - setup
安裝
$ npm install --save-dev babel-loader babel-core
**配置 **
在 Chapter03 的 Webpack 資源管理 一文中,介紹過使用 babel-loader 來處理 React 語法。
在 webpack.config.js 配置如下:
// 關于模塊配置
module: {
// 模塊規則(配置 loader、解析器等選項)
rules: [
{
// 語義解釋器,將 js/jsx 文件中的 es2015/react 語法自動轉為瀏覽器可識別的 Javascript 語法
test: /\.jsx?$/,
include: path.resolve(__dirname, "app"),
loader: "babel-loader",
},
]
},
?:flashlight: 示例
chapter03-jigsaw: (SOURCE)
chapter04-jigsaw: (SOURCE)
說明:
chapter04-jigsaw
和chapter03-jigsaw
相比,多了一個.babelrc
文件。它其實是將chapter03-jigsaw
中的webpack.common.js
文件里的 babel-loader 的配置移入了.babelrc
文件。這兩個代碼目錄的執行結果完全相同。
執行方法:
$ npm install # 開發環境 - 本地啟動一個訪問地址為 localhost:9000 的 web app $ npm run dev # 開發環境 - 生成一個 dist 目錄,其中打包了所有資源文件,在瀏覽器打開 index.html,可以看到和開發環境差不多的展示。 $ npm run prod # 清除輸出目錄 dist $ npm run clean
配置 Babel
?:pushpin: 提示:
由于
Babel
是一個非常靈活的通用編譯器,因此默認情況下它反而什么都不做。你需要通過配置文件,明確地告訴 Babel 應該要做什么。
.babelrc
.babelrc
文件是 Babel
的默認配置文件。
.babelrc
文件的內容形式就是序列化的 JSON。
該文件用來設置轉碼規則(presets)和插件(plugins),基本格式如下:
{
"presets": [],
"plugins": []
}
轉碼規則(preset)
轉碼規則可以告訴 Babel 去處理什么語法。
常見的轉碼規則有:
-
babel-preset-es2015
這是 ES2015(最新版本的 JavaScript 標準,也叫做 ES6)的轉碼規則。使用它后,Babel 可以將 ES6 語法轉碼為普通 JavaScript(即 ES5) 語法。
-
babel-preset-react
這是 React 的轉碼規則。使用它后,Babel 可以將 React 語法轉碼為普通 JavaScript 語法。
-
babel-preset-stage-x
這是 ES7 不同階段語法提案的轉碼規則。使用它后,Babel 可以將 ES7 不同階段語法轉碼為普通 JavaScript 語法。
?:pushpin: 提示:
JavaScript 還有一些提案,正在積極通過 TC39(ECMAScript 標準背后的技術委員會)的流程成為標準的一部分。
這個流程分為 5(0-4)個階段。 隨著提案得到越多的關注就越有可能被標準采納,于是他們就繼續通過各個階段,最終在階段 4 被標準正式采納。以下是4 個不同階段的(打包的)預設:
babel-preset-stage-0
babel-preset-stage-1
babel-preset-stage-2
babel-preset-stage-3
stage-4 預設是不存在的因為它就是上面的
es2015
預設。以上每種預設都依賴于緊隨的后期階段預設。例如,
babel-preset-stage-1
依賴babel-preset-stage-2
,后者又依賴babel-preset-stage-3
。
安裝
# es2015(即ES6)語法轉碼規則
$ npm install --save-dev babel-preset-es2015
# react 語法轉碼規則
$ npm install --save-dev babel-preset-react
# stage 是指 ES7 不同階段的語法轉碼規則,選裝一個即可
$ 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
中引入項目中實際需要的預設轉碼規則,讓 Babel 得以知道規則。
形式如下:
{
"presets": [
"es2015",
"react",
"stage-0"
],
"plugins": []
}
插件(plugins)
插件是 Babel 的核心。
Babel 插件大致分為三類:
-
轉碼插件
有很多種插件:將ES6 / ES2015轉換為ES5,轉換為ES3,minification,JSX,flow,實驗功能等等。
-
語法插件
這些只是使轉碼插件能夠解析某些功能(轉碼插件已經包含語法插件,因此這兩個功能你都不需要):
babel-plugin-syntax-x
-
助手
這些主要用于各種插件內部使用:
babel-helper-x
。
更多插件請在 npm 搜索(真的好多!)
更詳細介紹請參考:官方文檔 - 插件
在其它工具中配置
?:pushpin:? 提示:
除了在
.babelrc
文件中定義 Babel 配置。實際上,還可以在其他工具中對其進行配置。
在 package.json
中配置
可以在 package.json
文件的 babel
屬性中配置 Babel 規則。
配置方法與 .babelrc
文件完全相同。
形式如下:
"babel": {
"presets": [
"es2015"
]
"plugins": []
},
在 webpack.config.js
中配置
可以在 webpack.config.js
文件配置 babel-loader
時,直接在 options
屬性中配置 Babel 規則。
形式如下:
{
test: /\.jsx?$/,
include: path.resolve(__dirname, "app"),
exclude: /node_modules/,
loader: "babel-loader",
options: {
presets: [
[
"es2015",
{
"modules": false
}
],
"react"
],
plugins: [
"syntax-dynamic-import", // 動態導入插件
"react-hot-loader/babel" // 開啟 React 代碼的模塊熱替換(HMR)
]
},
}
執行 Babel 生成的代碼
即便你已經用 Babel 編譯了你的代碼,但這還不算完。
babel-polyfill
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
。
為了解決這個問題,我們使用一種叫做 Polyfill(代碼填充,也可譯作兼容性補丁) 的技術。 簡單地說,polyfill 即是在當前運行環境中用來復制(意指模擬性的復制,而不是拷貝)尚不存在的原生 api 的代碼。 能讓你提前使用還不可用的 APIs,Array.from
就是一個例子。
Babel 提供了 babel-polyfill
來支持 polyfill 。
安裝
$ npm install --save babel-polyfill
使用
然后,只需要在文件頂部導入 babel-polyfill
就可以了:
import "babel-polyfill";
babel-runtime
babel-runtime 與 polyfill 類似,不同之處在于它不修改全局范圍,并且與 babel-plugin-transform-runtime
(通常在庫/插件代碼中)一起使用。
為了實現 ECMAScript 規范的細節,Babel 會使用“助手”方法來保持生成代碼的整潔。
由于這些助手方法可能會特別長并且會被添加到每一個文件的頂部,因此你可以把它們統一移動到一個單一的“運行時(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"
]
}
現在,Babel 會把這樣的代碼:
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
這兩個助手方法放進每一個需要的文件里去了。