Babel 入門指南

Babel 入門指南

babel
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 面殖。

原因在與:

  1. 在同一臺(tái)機(jī)器上的不同項(xiàng)目或許會(huì)依賴不同版本的 Babel 并允許你有選擇的更新竖哩。
  2. 這意味著你對(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

使用

  1. 創(chuàng)建 index.js 文件:
console.log("Hello world!");

這是绍在,使用 node index.js 來運(yùn)行它是不會(huì)使用 Babel 來編譯的。所以我們需要設(shè)置 babel-register雹有。.

  1. 創(chuàng)建 register.js 文件:
require("babel-register");
require("./index.js");

這樣做可以把 Babel 注冊(cè)到 Node 的模塊系統(tǒng)中并開始編譯其中 require 的所有文件偿渡。

  1. 執(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-jigsawchapter03-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-runtimebabel-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è)需要的文件里去了忘渔。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市缰儿,隨后出現(xiàn)的幾起案子畦粮,更是在濱河造成了極大的恐慌,老刑警劉巖乖阵,帶你破解...
    沈念sama閱讀 206,126評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件宣赔,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡瞪浸,警方通過查閱死者的電腦和手機(jī)儒将,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來对蒲,“玉大人钩蚊,你說我怎么就攤上這事〉赴” “怎么了砰逻?”我有些...
    開封第一講書人閱讀 152,445評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)泛鸟。 經(jīng)常有香客問我诱渤,道長(zhǎng),這世上最難降的妖魔是什么谈况? 我笑而不...
    開封第一講書人閱讀 55,185評(píng)論 1 278
  • 正文 為了忘掉前任勺美,我火速辦了婚禮递胧,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘赡茸。我一直安慰自己缎脾,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評(píng)論 5 371
  • 文/花漫 我一把揭開白布占卧。 她就那樣靜靜地躺著遗菠,像睡著了一般。 火紅的嫁衣襯著肌膚如雪华蜒。 梳的紋絲不亂的頭發(fā)上辙纬,一...
    開封第一講書人閱讀 48,970評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音叭喜,去河邊找鬼贺拣。 笑死,一個(gè)胖子當(dāng)著我的面吹牛捂蕴,可吹牛的內(nèi)容都是我干的譬涡。 我是一名探鬼主播,決...
    沈念sama閱讀 38,276評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼啥辨,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼涡匀!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起溉知,我...
    開封第一講書人閱讀 36,927評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤陨瘩,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后级乍,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體舌劳,經(jīng)...
    沈念sama閱讀 43,400評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評(píng)論 2 323
  • 正文 我和宋清朗相戀三年卡者,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片客们。...
    茶點(diǎn)故事閱讀 37,997評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡崇决,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出底挫,到底是詐尸還是另有隱情恒傻,我是刑警寧澤,帶...
    沈念sama閱讀 33,646評(píng)論 4 322
  • 正文 年R本政府宣布建邓,位于F島的核電站盈厘,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏官边。R本人自食惡果不足惜沸手,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評(píng)論 3 307
  • 文/蒙蒙 一外遇、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧契吉,春花似錦跳仿、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至惑灵,卻和暖如春山上,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背英支。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評(píng)論 1 260
  • 我被黑心中介騙來泰國(guó)打工佩憾, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人潭辈。 一個(gè)月前我還...
    沈念sama閱讀 45,423評(píng)論 2 352
  • 正文 我出身青樓鸯屿,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親把敢。 傳聞我的和親對(duì)象是個(gè)殘疾皇子寄摆,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容