Babel 入門指南


Babel 入門指南

babel

​⚠️ 注意:

Babel 可以與很多構建工具(如 BrowserifyGruntGulp 等)進行集成。由於本教程選擇 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 集成

​📌 提示:

建議使用本地安裝方式安裝 babel-cli

原因在與:

  1. 在同一台機器上的不同項目或許會依賴不同版本的 Babel 並允許你有選擇的更新。
  2. 這意味着你對工作環境沒有隱式依賴,這讓你的項目有很好的可移植性並且易於安裝。

本地安裝 babel-cli ,直接使用 babel 命令將無法識別。你可以選在在 package.json 文件的  scripts 屬性中定義命令。npm 會自動找到本地安裝的庫。

{
  "scripts": {
    "build": "babel src -d lib"
  },
  "devDependencies": {
    "babel-cli": "^6.0.0"
  },
}

現在可以在終端里執行命令:

$ npm run build

​🔦 示例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,或許能更好地融入你的項目設置。

​⚠️ 注意:

這種方法並不適合正式產品環境使用。 直接部署用此方式編譯的代碼不是好的做法。 在部署之前預先編譯會更好。

不過用在構建腳本或是其他本地運行的腳本中是非常合適的。

安裝

$ npm install --save-dev babel-register

使用

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

這是,使用 node index.js 來運行它是不會使用 Babel 來編譯的。所以我們需要設置 babel-register。.

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

這樣做可以把 Babel 注冊到 Node 的模塊系統中並開始編譯其中 require 的所有文件。

  1. 執行命令

    現在我們可以使用 register.js 來代替 node index.js 來運行了。

$ node register.js

需要注意的是:你不能在你要編譯的文件內同時注冊 Babel,因為 node 會在 Babel 編譯它之前就將它執行了。

​🔦 示例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 集成

​📌 提示:

本教程由於選擇的編譯工具為 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",
    },
  ]
},

​🔦 示例

chapter03-jigsaw: (SOURCE)

chapter04-jigsaw: (SOURCE)

說明:

chapter04-jigsawchapter03-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

​📌 提示:

由於 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 語法。

    ​📌 提示:

    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 搜索(真的好多!)

更詳細介紹請參考:官方文檔 - 插件

在其它工具中配置

​📌​ 提示:

除了在 .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 這兩個助手方法放進每一個需要的文件里去了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM