【Web技術】848- 超棒的 Babel 上手指南

此文檔翻譯自 https://github.com/jamiebuilds/babel-handbook,由圖雀醬審驗。

這個文檔涵蓋了所有你想知道的關於 Babel 及其相關工具使用的所有內容。

目錄

  • 引言
  • 配置 Babel 環境
    • babel-cli
    • 在項目內部運行 Babel CLI
    • babel-register
    • babel-node
    • babel-core
  • 配置 Babel
    • .babelrc
    • babel-preset-es2015
    • babel-preset-react
    • babel-preset-stage-x
  • 執行 babel 生成的代碼
    • babel-polyfill
    • babel-runtime
  • 配置 Babel (進階版)
    • 手動指定插件
    • 插件選項
    • 基於環境定製 Babel
    • 構建自己的 Preset
  • Babel 和其他工具
    • 靜態分析工具
    • Linting
    • 文檔
    • 框架

引言

Babel 是一個用於 JavaScript 的通用多用途編譯器,使用 Babel 可以使用(或創建)下一代 的JavaScript,以及下一代 JavaScript 工具。

作爲一門語言,JavaScript 不斷髮展,帶來了很多新的規範和建議,使用 Babel 可以讓你在這些新的規範和建議全面普及之前就提前使用它們。

Babel 通過將最新標準的 JavaScript 代碼編譯爲已經在目前可以工作的代碼來實現上一段提到的內容。這個過程被稱爲 “源代碼到源代碼” 的編譯,這也被成爲 “轉換”

例如,Babel 可以將最新的 ES2015 的箭頭函數語法從:

const square = n => n * n;

轉換成下面的內容:

const square = function square(n{
  return n * n;
};

然而,Babel 可以勝任更多的工作,因爲Babel 支持語法擴展,例如 React 的 JSX 語法或者靜態類型檢查的 Flow 語法。

更近一步,在 Babel 中一切皆插件,而每個人都可以充分利用 Babel 的強大能力來創建屬於自己的插件。且 Babel 被組織成幾個核心的模塊,允許用戶利用這些模塊來構建下一代 JavaScript 工具鏈。

許多人也是這樣去做的,Babel 的生態系統正在茁長的成長。在這本 Babel 手冊中,我將講解 Babel 內建的一些工具以及社區裏的一些擁有的工具。

Babel 模塊介紹

因爲 JavaScript 社區沒有標準的構建工具,框架或平臺等,Babel 官方性與其他所有的主要工具進行了集成。無論是來自 Gulp、Browserify,或者是 Ember、Meteor,亦或是 Webpack 等,無論你的啓動工具是什麼,Babel 都存在一些官方性的集成。

就本手冊而言,我們將介紹設置Babel的內置方法,但是您也可以訪問交互式設置頁面[1]以瞭解所有集成。

注意:本指南將參考諸如 nodenpm 之類的命令行工具。在繼續進行任何操作之前,您應該對這些工具感到滿意。

babel-cli

Babel的CLI是從命令行使用Babel編譯文件的簡單方法。

讓我們首先在全局安裝它以學習基礎知識。

$ npm install --global babel-cli

我們可以像這樣編譯我們的第一個文件:

$ babel my-file.js

這會將編譯後的輸出直接轉儲到您的終端中。要將其寫入文件,我們將指定 --out-file 或 -o 。

$ babel example.js --out-file compiled.js
# or
$ babel example.js -o compiled.js

如果我們想將整個目錄編譯成一個新目錄,可以使用 --out-dir 或 -d 來完成。

$ babel src --out-dir lib
# or
$ babel src -d lib

從項目中運行Babel CLI

雖然您可以在計算機上全局安裝Babel CLI,但最好逐個項目在本地安裝它。

這有兩個主要原因。

  • 同一臺計算機上的不同項目可能取決於Babel的不同版本,從而允許您一次更新一個版本。
  • 這意味着您對工作的環境沒有隱式依賴。使您的項目更加可移植且易於設置。

我們可以通過運行以下命令在本地安裝Babel CLI:

$ npm install --save-dev babel-cli

注意:由於在全局範圍內運行 Babel 通常是一個壞主意,因此您可能需要通過運行以下命令來卸載全局副本:

$ npm uninstall --global babel-cli

完成安裝後,您的 package.json 文件應如下所示:

{
  "name""my-project",
  "version""1.0.0",
  "devDependencies": {
    "babel-cli""^6.0.0"
  }
}

現在,與其直接從命令行運行 Babel,不如將命令放入使用本地版本的 npm 腳本中。只需在您的 package.json 中添加一個 “script” 字段,然後將 babel 命令放入其中即可進行構建。

  {
    "name": "my-project",
    "version": "1.0.0",
+   "scripts": {
+     "build": "babel src -d lib"
+   },
    "devDependencies": {
      "babel-cli": "^6.0.0"
    }
  }

現在,從我們的終端我們可以運行:

npm run build

這將以與以前相同的方式運行Babel,只是現在我們正在使用本地副本。

babel-register

運行Babel的下一個最常見的方法是通過 babel-register 。通過此選項,您僅需要文件即可運行 Babel,這可能會更好地與您的設置集成。

請注意,這並非供生產使用。部署以這種方式編譯的代碼被認爲是不好的做法。最好在部署之前提前進行編譯。但是,這對於構建腳本或您在本地運行的其他事情非常有效。

首先讓我們在項目中創建一個 index.js 文件。

console.log("Hello world!");

如果我們使用 node index.js 來運行它,那麼 Babel 不會編譯它。因此,我們需要先設置 babel-register 。

首先安裝 babel-register 。

$ npm install --save-dev babel-register

接下來,在項目中創建一個 register.js 文件,並編寫以下代碼:

require("babel-register");
require("./index.js");

這是在 Node 的模塊系統中註冊 Babel 並開始編譯每個 require 的文件。

現在,我們可以使用 node egister.js 代替運行 node index.js 。

$ node register.js

注意:您不能在要編譯的文件中註冊 Babel。在 Babel 有機會編譯文件之前,Node 正在執行文件。

require("babel-register");

// not compiled:
console.log("Hello world!");

babel-node

如果您只是通過 node  CLI 運行某些代碼,則集成 Babel 的最簡單方法可能是使用 babel-node  CLI,這在很大程度上只是對 node CLI 的替代。

請注意,這並非供生產使用。部署以這種方式編譯的代碼被認爲是不好的做法。最好在部署之前提前進行編譯。但是,這對於構建腳本或您在本地運行的其他事情非常有效。

首先,請確保您已安裝 babel-cli 。

$ npm install --save-dev babel-cli

**注意:**如果您想知道爲什麼要在本地安裝此軟件,請在上面的項目部分中閱讀 “從項目中運行 Babel CLI”。

然後,將運行 node 的任何位置替換爲 babel-node 。

如果您使用的是 npm script ,則只需執行以下操作:

  {
    "scripts": {
-     "script-name": "node script.js"
+     "script-name": "babel-node script.js"
    }
  }

否則,您將需要寫出通向 babel-node 本身的路徑。

- node script.js
+ ./node_modules/.bin/babel-node script.js

babel-core

如果出於某種原因需要在代碼中使用 Babel,則可以使用 babel-core 軟件包本身。

首先安裝 babel-core 。

$ npm install babel-core
var babel = require("babel-core");

如果您具有 JavaScript 字符串,則可以直接使用 babel.transform 對其進行編譯。

babel.transform("code();", options);
// => { code, map, ast }

如果使用文件,則可以使用異步api:

babel.transformFile("filename.js", options, function(err, result{
  result; // => { code, map, ast }
});

如果您出於任何原因已經擁有Babel AST,則可以直接從AST轉換。

babel.transformFromAst(ast, code, options);
// => { code, map, ast }

對於上述所有方法, options 可以傳遞指南可以從這裏瞭解 https://babeljs.io/docs/usage/api/#options[2]

配置 Babel

您現在可能已經注意到,僅運行 Babel 似乎除了將 JavaScript 文件從一個位置複製到另一個位置之外沒有執行任何其他操作。

這是因爲我們尚未告訴 Babel 該做什麼事情。

由於Babel是通用編譯器,它以多種不同的方式使用,因此默認情況下它不會執行任何操作。您必須明確告訴Babel 它應該做什麼。

您可以通過安裝 plugins 或 presets (plugins 組)爲Babel提供操作說明。

.babelrc

在我們開始告訴 Babel 怎麼做之前。我們需要創建一個配置文件。您需要做的就是在項目的根目錄下創建一個 .babelrc 文件。從這樣開始:

{
  "presets": [],
  "plugins": []
}

該文件是您配置 Babel 以執行所需操作的方式。

注意:雖然您還可以通過其他方式將選項傳遞給 Babel,但 .babelrc 文件是約定俗成的,也是最好的方法。

babel-preset-es2015

讓我們首先告訴 Babel 將 ES2015(JavaScript標準的最新版本,也稱爲ES6)編譯爲ES5(當今大多數JavaScript環境中可用的版本)。

我們將通過安裝“ es2015” Babel預設來做到這一點(當然目前瀏覽器支持了絕大部分 ES2015 的特性了,這裏是用作演示,使用形式是一致的):

$ npm install --save-dev babel-preset-es2015

接下來,我們將修改 .babelrc 以包括該預設。

  {
    "presets": [
+     "es2015"
    ],
    "plugins": []
  }

babel-preset-react

設置 React 同樣簡單。只需安裝預設:

$ npm install --save-dev babel-preset-react

然後將預設添加到您的 .babelrc 文件中:

  {
    "presets": [
      "es2015",
+     "react"
    ],
    "plugins": []
  }

babel-preset-stage-x

JavaScript還提出了一些建議,這些建議正在通過TC39(ECMAScript標準背後的技術委員會)流程納入標準。

此過程分爲5個階段(0-4)。隨着提案獲得更大的吸引力,並更有可能被採納爲標準,它們經歷了各個階段,最終在階段4被接納爲標準。

這些以babel的形式捆綁爲4種不同的預設:

  • babel-preset-stage-0
  • babel-preset-stage-1
  • babel-preset-stage-2
  • babel-preset-stage-3

請注意,沒有階段 4 的 preset ,因爲它只是上面的 es2015 預設。

這些預設中的每個預設都需要用於後續階段的預設。即 babel-preset-stage-1 需要 babel-preset-stage-2 ,而 babel-preset-stage-3  也需要。

安裝您感興趣的 stage 很簡單:

$ npm install --save-dev babel-preset-stage-2

然後,您可以將其添加到您的 .babelrc 配置中。

  {
    "presets": [
      "es2015",
      "react",
+     "stage-2"
    ],
    "plugins": []
  }

執行 Babel 生成的代碼

目前,您已經使用Babel編譯了代碼,但這還不是故事的結局。

babel-polyfill

幾乎所有未來 JavaScript 語法都可以使用 Babel 進行編譯,但 API 並非如此。

例如,以下代碼具有需要編譯的箭頭函數功能:

function addAll({
  return Array.from(arguments).reduce((a, b) => a + b);
}

在編譯之後會變成如下這樣:

function addAll({
  return Array.from(arguments).reduce(function(a, b{
    return a + b;
  });
}

但是,由於 Array.from 並非在每個JavaScript環境中都存在,因此在編譯之後它仍然無法使用:

Uncaught TypeError: Array.from is not a function

爲了解決這個問題,我們使用一種叫做 Polyfill[3] 的東西。簡而言之,Polyfill 是一段代碼,該代碼複製當前運行時中不存在的 API,允許您在當前環境可用之前能提前使用 Array.from 等 API。

Babel使用出色的 core-js[4] 作爲其polyfill,以及定製的 regenerator[5] 運行時,以使生成器和異步函數正常工作。

要包含 Babel polyfill,請首先使用npm安裝它:

$ npm install --save babel-polyfill

然後只需將 polyfill 包含在任何需要它的文件的頂部:

import "babel-polyfill";

babel-runtime

爲了實現 ECMAScript 規範的詳細信息,Babel將使用 “helper” 方法來保持生成的代碼乾淨。

由於這些 “helper” 方法會變得很長,而且它們被添加到每個文件的頂部,因此您可以將它們移動到 require 的單個“運行時”中。

首先安裝 babel-plugin-transform-runtime 和 babel-runtime :

$ npm install --save-dev babel-plugin-transform-runtime
$ npm install --save babel-runtime

然後更新您的 .babelrc :

  {
    "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",
    valuefunction method({}
  }]);

  return Foo;
}();

而不是將 _classCallCheck 和 _createClass helper 函數放在需要的每個文件中。

配置 Babel(進階版)

大多數人都可以通過僅使用內置預設來使用 Babel,但是 Babel 所展現的功能遠不止於此。

手動指定插件

Babel 預設只是預配置插件的集合,如果您想做不同的事情,可以手動指定插件。這幾乎與預設完全相同。

首先安裝一個插件:

$ npm install --save-dev babel-plugin-transform-es2015-classes

然後將 plugins 字段添加到您的 .babelrc 中。

  {
+   "plugins": [
+     "transform-es2015-classes"
+   ]
  }

這使您可以更精確地控制正在運行的確切的 transforms 。

有關官方插件的完整列表,請參見Babel插件頁面[6]

還請看一下社區構建的所有插件[7]。如果您想學習如何編寫自己的插件,請閱讀Babel插件手冊[8](圖雀社區將在之後翻譯這本插件手冊,敬請期待~)。

插件選項

許多插件還具有將其配置爲不同行爲的 option 。例如,許多 transform 都具有 loose 模式,該模式會放棄某些規範行爲,而傾向於使用更簡單,性能更高的代碼。

要將選項添加到插件,只需進行以下更改:

  {
    "plugins": [
-     "transform-es2015-classes"
+     ["transform-es2015-classes", { "loose": true }]
    ]
  }

根據環境定製 Babel

Babel插件解決了許多不同的任務。其中許多是開發工具,可以幫助您調試代碼或與工具集成。還有許多用於優化生產中代碼的插件。

因此,通常需要基於環境的 Babel 配置。您可以使用 .babelrc 文件輕鬆完成此操作。

  {
    "presets": ["es2015"],
    "plugins": [],
+   "env": {
+     "development": {
+       "plugins": [...]
+     },
+     "production": {
+       "plugins": [...]
+     }
    }
  }

Babel將根據當前環境在 env 內部啓用配置。

當前環境將使用 process.env.BABEL_ENV 。當 BABEL_ENV 不可用時,它將回退到 NODE_ENV ,如果不可用,則默認爲“ development ”。

Unix

$ BABEL_ENV=production [COMMAND]
$ NODE_ENV=production [COMMAND]

Windows

$ SET BABEL_ENV=production
$ [COMMAND]

注意:[COMMAND] 是您用來運行Babel的任何東西(即 babel , babel-node ,或者如果您正在使用 babel-register 鉤子,則可能只是 node )。

提示:如果要讓命令在 Unix 和 Windows 跨平臺上運行,請使用 cross-env[9]

構建自己的預設

手動指定插件?插件選項?基於環境的設置?對於所有項目,所有這些配置似乎都需要重複很多次。

因此,我們鼓勵社區創建自己的預設。這可以是您整個公司[10]的預設。

創建預設很容易。假設您有以下 .babelrc 文件:

{
  "presets": [
    "es2015",
    "react"
  ],
  "plugins": [
    "transform-flow-strip-types"
  ]
}

您需要做的就是按照命名約定 babel-preset-* 創建一個新項目(請對此命名空間負責!),並創建兩個文件。

首先,創建一個新的 package.json 文件,該文件具有您的預設所需的 dependencies 關係。

{
  "name""babel-preset-my-awesome-preset",
  "version""1.0.0",
  "author""James Kyle <[email protected]>",
  "dependencies": {
    "babel-preset-es2015""^6.3.13",
    "babel-preset-react""^6.3.13",
    "babel-plugin-transform-flow-strip-types""^6.3.15"
  }
}

然後創建一個 index.js 文件,該文件導出 .babelrc 文件的內容,並用 require 調用替換插件/預設字符串。

module.exports = {
  presets: [
    require("babel-preset-es2015"),
    require("babel-preset-react")
  ],
  plugins: [
    require("babel-plugin-transform-flow-strip-types")
  ]
};

然後只需將其發佈到 npm,就可以像使用任何預設一樣使用它。

Babel 和其他工具結合

一旦掌握了 Babel,Babel 便會很直接地進行設置,但是使用其他工具進行設置可能非常困難。但是,我們嘗試與其他項目緊密合作,以使體驗儘可能輕鬆。

靜態分析工具

較新的標準爲語言帶來了許多新語法,而靜態分析工具纔剛剛開始利用它。

Linting

ESLint 是最受歡迎的 Lint 工具之一,因此,我們維護了官方的 babel-eslint[11] 集成。首先安裝 eslint 和 babel-eslint 。

$ npm install --save-dev eslint babel-eslint

接下來,在項目中創建或使用現有的 .eslintrc 文件,並將解析器設置爲 babel-eslint 。

  {
+   "parser": "babel-eslint",
    "rules": {
      ...
    }
  }

現在將一個 lint  任務添加到您的 npm package.json 腳本中:

  {
    "name": "my-module",
    "scripts": {
+     "lint": "eslint my-files.js"
    },
    "devDependencies": {
      "babel-eslint": "...",
      "eslint": "..."
    }
  }

然後只需運行任務即可完成所有設置。

$ npm run lint

有關更多信息,請查閱 babel-eslint[12]eslint[13]文檔。

文檔

使用Babel,ES2015和Flow,您可以推斷出很多有關您的代碼的信息。使用documentation.js[14],您可以非常輕鬆地生成詳細的API文檔。

Documentation.js在後臺使用Babel支持所有最新語法,包括Flow註釋,以便在代碼中聲明類型。

框架

現在,所有主要的JavaScript框架都專注於圍繞語言的未來調整其API。因此,在工具中進行了大量工作。

框架不僅有機會使用Babel,而且有機會以改善用戶體驗的方式對其進行擴展。

React

React極大地改變了其API以使其與ES2015類保持一致(在此處瞭解更新的API)。更進一步,React依賴Babel來編譯它的JSX語法,不贊成Babel來使用它自己的自定義工具。您可以按照上述說明開始設置 babel-preset-react 程序包。

React社區接受了Babel並與之合作。社區[15]現在進行了許多轉換。

最著名的是 babel-plugin-react-transform 插件,結合了許多特定於 React 的轉換,可以啓用熱模塊重裝和其他調試實用程序。

參考資料

[1]

交互式設置頁面: https://babeljs.io/en/setup/

[2]

https://babeljs.io/docs/usage/api/#options: https://babeljs.io/docs/usage/api/#options

[3]

Polyfill: https://www.google.com/search?q=%E4%BB%80%E4%B9%88%E6%98%AF+polyfill&oq=%E4%BB%80%E4%B9%88%E6%98%AF+polyfill&aqs=chrome..69i57j0i12.3956j1j4&sourceid=chrome&ie=UTF-8

[4]

core-js: https://github.com/zloirock/core-js

[5]

regenerator: https://github.com/facebook/regenerator

[6]

Babel插件頁面: http://babeljs.io/docs/plugins/

[7]

所有插件: https://www.npmjs.com/search?q=babel-plugin

[8]

Babel插件手冊: https://github.com/jamiebuilds/babel-handbook/blob/master/translations/en/plugin-handbook.md

[9]

cross-env: https://www.npmjs.com/package/cross-env

[10]

公司: https://github.com/cloudflare/babel-preset-cf

[11]

babel-eslint: https://github.com/babel/babel/tree/master/eslint/babel-eslint-parser

[12]

babel-eslint: https://github.com/babel/babel/tree/master/eslint/babel-eslint-parser

[13]

eslint: https://eslint.org/

[14]

documentation.js: http://documentation.js.org/

[15]

社區: https://www.npmjs.com/search?q=babel-plugin+react

1. JavaScript 重溫系列(22篇全)
2. ECMAScript 重溫系列(10篇全)
3. JavaScript設計模式 重溫系列(9篇全)
4.  正則 / 框架 / 算法等 重溫系列(16篇全)
5.  Webpack4 入門(上) ||  Webpack4 入門(下)
6.  MobX 入門(上)  ||   MobX 入門(下)
7. 100 +篇原創系列彙總

回覆“加羣”與大佬們一起交流學習~

點擊“閱讀原文”查看 100+ 篇原創文章

本文分享自微信公衆號 - 前端自習課(FE-study)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章