前端也要懂編譯:Babel 最全上手指南
此文檔翻譯自 https://github.com/jamiebuilds/babel-handbook,由圖雀醬審驗(yàn)。
這個(gè)文檔涵蓋了所有你想知道的關(guān)于 Babel 及其相關(guān)工具使用的所有內(nèi)容。
目錄
引言 配置 Babel 環(huán)境 babel-cli在項(xiàng)目?jī)?nèi)部運(yùn)行 Babel CLI babel-registerbabel-nodebabel-core配置 Babel .babelrcbabel-preset-es2015babel-preset-reactbabel-preset-stage-x執(zhí)行 babel 生成的代碼 babel-polyfillbabel-runtime配置 Babel (進(jìn)階版) 手動(dòng)指定插件 插件選項(xiàng) 基于環(huán)境定制 Babel 構(gòu)建自己的 Preset Babel 和其他工具 靜態(tài)分析工具 Linting 文檔 框架
引言
Babel 是一個(gè)用于 JavaScript 的通用多用途編譯器,使用 Babel 可以使用(或創(chuàng)建)下一代 的JavaScript,以及下一代 JavaScript 工具。
作為一門語(yǔ)言,JavaScript 不斷發(fā)展,帶來(lái)了很多新的規(guī)范和建議,使用 Babel 可以讓你在這些新的規(guī)范和建議全面普及之前就提前使用它們。
Babel 通過(guò)將最新標(biāo)準(zhǔn)的 JavaScript 代碼編譯為已經(jīng)在目前可以工作的代碼來(lái)實(shí)現(xiàn)上一段提到的內(nèi)容。這個(gè)過(guò)程被稱為 “源代碼到源代碼” 的編譯,這也被成為 “轉(zhuǎn)換”。
例如,Babel 可以將最新的 ES2015 的箭頭函數(shù)語(yǔ)法從:
const square = n => n * n;
轉(zhuǎn)換成下面的內(nèi)容:
const square = function square(n) {
return n * n;
};
然而,Babel 可以勝任更多的工作,因?yàn)锽abel 支持語(yǔ)法擴(kuò)展,例如 React 的 JSX 語(yǔ)法或者靜態(tài)類型檢查的 Flow 語(yǔ)法。
更近一步,在 Babel 中一切皆插件,而每個(gè)人都可以充分利用 Babel 的強(qiáng)大能力來(lái)創(chuàng)建屬于自己的插件。且 Babel 被組織成幾個(gè)核心的模塊,允許用戶利用這些模塊來(lái)構(gòu)建下一代 JavaScript 工具鏈。
許多人也是這樣去做的,Babel 的生態(tài)系統(tǒng)正在茁長(zhǎng)的成長(zhǎng)。在這本 Babel 手冊(cè)中,我將講解 Babel 內(nèi)建的一些工具以及社區(qū)里的一些擁有的工具。
Babel 模塊介紹
因?yàn)?JavaScript 社區(qū)沒(méi)有標(biāo)準(zhǔn)的構(gòu)建工具,框架或平臺(tái)等,Babel 官方性與其他所有的主要工具進(jìn)行了集成。無(wú)論是來(lái)自 Gulp、Browserify,或者是 Ember、Meteor,亦或是 Webpack 等,無(wú)論你的啟動(dòng)工具是什么,Babel 都存在一些官方性的集成。
就本手冊(cè)而言,我們將介紹設(shè)置Babel的內(nèi)置方法,但是您也可以訪問(wèn)交互式設(shè)置頁(yè)面[1]以了解所有集成。
注意:本指南將參考諸如
node和npm之類的命令行工具。在繼續(xù)進(jìn)行任何操作之前,您應(yīng)該對(duì)這些工具感到滿意。
babel-cli
Babel的CLI是從命令行使用Babel編譯文件的簡(jiǎn)單方法。
讓我們首先在全局安裝它以學(xué)習(xí)基礎(chǔ)知識(shí)。
$ npm install --global babel-cli
我們可以像這樣編譯我們的第一個(gè)文件:
$ babel my-file.js
這會(huì)將編譯后的輸出直接轉(zhuǎn)儲(chǔ)到您的終端中。要將其寫(xiě)入文件,我們將指定 --out-file 或 -o 。
$ babel example.js --out-file compiled.js
# or
$ babel example.js -o compiled.js
如果我們想將整個(gè)目錄編譯成一個(gè)新目錄,可以使用 --out-dir 或 -d 來(lái)完成。
$ babel src --out-dir lib
# or
$ babel src -d lib
從項(xiàng)目中運(yùn)行Babel CLI
雖然您可以在計(jì)算機(jī)上全局安裝Babel CLI,但最好逐個(gè)項(xiàng)目在本地安裝它。
這有兩個(gè)主要原因。
同一臺(tái)計(jì)算機(jī)上的不同項(xiàng)目可能取決于Babel的不同版本,從而允許您一次更新一個(gè)版本。 這意味著您對(duì)工作的環(huán)境沒(méi)有隱式依賴。使您的項(xiàng)目更加可移植且易于設(shè)置。
我們可以通過(guò)運(yùn)行以下命令在本地安裝Babel CLI:
$ npm install --save-dev babel-cli
注意:由于在全局范圍內(nèi)運(yùn)行 Babel 通常是一個(gè)壞主意,因此您可能需要通過(guò)運(yùn)行以下命令來(lái)卸載全局副本:
$ npm uninstall --global babel-cli
完成安裝后,您的 package.json 文件應(yīng)如下所示:
{
"name": "my-project",
"version": "1.0.0",
"devDependencies": {
"babel-cli": "^6.0.0"
}
}
現(xiàn)在,與其直接從命令行運(yùn)行 Babel,不如將命令放入使用本地版本的 npm 腳本中。只需在您的 package.json 中添加一個(gè) “script” 字段,然后將 babel 命令放入其中即可進(jìn)行構(gòu)建。
{
"name": "my-project",
"version": "1.0.0",
+ "scripts": {
+ "build": "babel src -d lib"
+ },
"devDependencies": {
"babel-cli": "^6.0.0"
}
}
現(xiàn)在,從我們的終端我們可以運(yùn)行:
npm run build
這將以與以前相同的方式運(yùn)行Babel,只是現(xiàn)在我們正在使用本地副本。
babel-register
運(yùn)行Babel的下一個(gè)最常見(jiàn)的方法是通過(guò) babel-register 。通過(guò)此選項(xiàng),您僅需要文件即可運(yùn)行 Babel,這可能會(huì)更好地與您的設(shè)置集成。
請(qǐng)注意,這并非供生產(chǎn)使用。部署以這種方式編譯的代碼被認(rèn)為是不好的做法。最好在部署之前提前進(jìn)行編譯。但是,這對(duì)于構(gòu)建腳本或您在本地運(yùn)行的其他事情非常有效。
首先讓我們?cè)陧?xiàng)目中創(chuàng)建一個(gè) index.js 文件。
console.log("Hello world!");
如果我們使用 node index.js 來(lái)運(yùn)行它,那么 Babel 不會(huì)編譯它。因此,我們需要先設(shè)置 babel-register 。
首先安裝 babel-register 。
$ npm install --save-dev babel-register
接下來(lái),在項(xiàng)目中創(chuàng)建一個(gè) register.js 文件,并編寫(xiě)以下代碼:
require("babel-register");
require("./index.js");
這是在 Node 的模塊系統(tǒng)中注冊(cè) Babel 并開(kāi)始編譯每個(gè) require 的文件。
現(xiàn)在,我們可以使用 node egister.js 代替運(yùn)行 node index.js 。
$ node register.js
注意:您不能在要編譯的文件中注冊(cè) Babel。在 Babel 有機(jī)會(huì)編譯文件之前,Node 正在執(zhí)行文件。
require("babel-register");
// not compiled:
console.log("Hello world!");
babel-node
如果您只是通過(guò) node CLI 運(yùn)行某些代碼,則集成 Babel 的最簡(jiǎn)單方法可能是使用 babel-node CLI,這在很大程度上只是對(duì) node CLI 的替代。
請(qǐng)注意,這并非供生產(chǎn)使用。部署以這種方式編譯的代碼被認(rèn)為是不好的做法。最好在部署之前提前進(jìn)行編譯。但是,這對(duì)于構(gòu)建腳本或您在本地運(yùn)行的其他事情非常有效。
首先,請(qǐng)確保您已安裝 babel-cli 。
$ npm install --save-dev babel-cli
**注意:**如果您想知道為什么要在本地安裝此軟件,請(qǐng)?jiān)谏厦娴捻?xiàng)目部分中閱讀 “從項(xiàng)目中運(yùn)行 Babel CLI”。
然后,將運(yùn)行 node 的任何位置替換為 babel-node 。
如果您使用的是 npm script ,則只需執(zhí)行以下操作:
{
"scripts": {
- "script-name": "node script.js"
+ "script-name": "babel-node script.js"
}
}
否則,您將需要寫(xiě)出通向 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 對(duì)其進(jìn)行編譯。
babel.transform("code();", options);
// => { code, map, ast }
如果使用文件,則可以使用異步api:
babel.transformFile("filename.js", options, function(err, result) {
result; // => { code, map, ast }
});
如果您出于任何原因已經(jīng)擁有Babel AST,則可以直接從AST轉(zhuǎn)換。
babel.transformFromAst(ast, code, options);
// => { code, map, ast }
對(duì)于上述所有方法, options 可以傳遞指南可以從這里了解 https://babeljs.io/docs/usage/api/#options[2]。
配置 Babel
您現(xiàn)在可能已經(jīng)注意到,僅運(yùn)行 Babel 似乎除了將 JavaScript 文件從一個(gè)位置復(fù)制到另一個(gè)位置之外沒(méi)有執(zhí)行任何其他操作。
這是因?yàn)槲覀兩形锤嬖V Babel 該做什么事情。
由于Babel是通用編譯器,它以多種不同的方式使用,因此默認(rèn)情況下它不會(huì)執(zhí)行任何操作。您必須明確告訴Babel 它應(yīng)該做什么。
您可以通過(guò)安裝 plugins 或 presets (plugins 組)為Babel提供操作說(shuō)明。
.babelrc
在我們開(kāi)始告訴 Babel 怎么做之前。我們需要?jiǎng)?chuàng)建一個(gè)配置文件。您需要做的就是在項(xiàng)目的根目錄下創(chuàng)建一個(gè) .babelrc 文件。從這樣開(kāi)始:
{
"presets": [],
"plugins": []
}
該文件是您配置 Babel 以執(zhí)行所需操作的方式。
注意:雖然您還可以通過(guò)其他方式將選項(xiàng)傳遞給 Babel,但
.babelrc文件是約定俗成的,也是最好的方法。
babel-preset-es2015
讓我們首先告訴 Babel 將 ES2015(JavaScript標(biāo)準(zhǔn)的最新版本,也稱為ES6)編譯為ES5(當(dāng)今大多數(shù)JavaScript環(huán)境中可用的版本)。
我們將通過(guò)安裝“ es2015” Babel預(yù)設(shè)來(lái)做到這一點(diǎn)(當(dāng)然目前瀏覽器支持了絕大部分 ES2015 的特性了,這里是用作演示,使用形式是一致的):
$ npm install --save-dev babel-preset-es2015
接下來(lái),我們將修改 .babelrc 以包括該預(yù)設(shè)。
{
"presets": [
+ "es2015"
],
"plugins": []
}
babel-preset-react
設(shè)置 React 同樣簡(jiǎn)單。只需安裝預(yù)設(shè):
$ npm install --save-dev babel-preset-react
然后將預(yù)設(shè)添加到您的 .babelrc 文件中:
{
"presets": [
"es2015",
+ "react"
],
"plugins": []
}
babel-preset-stage-x
JavaScript還提出了一些建議,這些建議正在通過(guò)TC39(ECMAScript標(biāo)準(zhǔn)背后的技術(shù)委員會(huì))流程納入標(biāo)準(zhǔn)。
此過(guò)程分為5個(gè)階段(0-4)。隨著提案獲得更大的吸引力,并更有可能被采納為標(biāo)準(zhǔn),它們經(jīng)歷了各個(gè)階段,最終在階段4被接納為標(biāo)準(zhǔn)。
這些以babel的形式捆綁為4種不同的預(yù)設(shè):
babel-preset-stage-0babel-preset-stage-1babel-preset-stage-2babel-preset-stage-3
請(qǐng)注意,沒(méi)有階段 4 的 preset ,因?yàn)樗皇巧厦娴?es2015 預(yù)設(shè)。
這些預(yù)設(shè)中的每個(gè)預(yù)設(shè)都需要用于后續(xù)階段的預(yù)設(shè)。即 babel-preset-stage-1 需要 babel-preset-stage-2 ,而 babel-preset-stage-3 也需要。
安裝您感興趣的 stage 很簡(jiǎn)單:
$ npm install --save-dev babel-preset-stage-2
然后,您可以將其添加到您的 .babelrc 配置中。
{
"presets": [
"es2015",
"react",
+ "stage-2"
],
"plugins": []
}
執(zhí)行 Babel 生成的代碼
目前,您已經(jīng)使用Babel編譯了代碼,但這還不是故事的結(jié)局。
babel-polyfill
幾乎所有未來(lái) JavaScript 語(yǔ)法都可以使用 Babel 進(jìn)行編譯,但 API 并非如此。
例如,以下代碼具有需要編譯的箭頭函數(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;
});
}
但是,由于 Array.from 并非在每個(gè)JavaScript環(huán)境中都存在,因此在編譯之后它仍然無(wú)法使用:
Uncaught TypeError: Array.from is not a function
為了解決這個(gè)問(wèn)題,我們使用一種叫做 Polyfill[3] 的東西。簡(jiǎn)而言之,Polyfill 是一段代碼,該代碼復(fù)制當(dāng)前運(yùn)行時(shí)中不存在的 API,允許您在當(dāng)前環(huán)境可用之前能提前使用 Array.from 等 API。
Babel使用出色的 core-js[4] 作為其polyfill,以及定制的 regenerator[5] 運(yùn)行時(shí),以使生成器和異步函數(shù)正常工作。
要包含 Babel polyfill,請(qǐng)首先使用npm安裝它:
$ npm install --save babel-polyfill
然后只需將 polyfill 包含在任何需要它的文件的頂部:
import "babel-polyfill";
babel-runtime
為了實(shí)現(xiàn) ECMAScript 規(guī)范的詳細(xì)信息,Babel將使用 “helper” 方法來(lái)保持生成的代碼干凈。
由于這些 “helper” 方法會(huì)變得很長(zhǎng),而且它們被添加到每個(gè)文件的頂部,因此您可以將它們移動(dòng)到 require 的單個(gè)“運(yùn)行時(shí)”中。
首先安裝 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"
]
}
現(xiàn)在,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 helper 函數(shù)放在需要的每個(gè)文件中。
配置 Babel(進(jìn)階版)
大多數(shù)人都可以通過(guò)僅使用內(nèi)置預(yù)設(shè)來(lái)使用 Babel,但是 Babel 所展現(xiàn)的功能遠(yuǎn)不止于此。
手動(dòng)指定插件
Babel 預(yù)設(shè)只是預(yù)配置插件的集合,如果您想做不同的事情,可以手動(dòng)指定插件。這幾乎與預(yù)設(shè)完全相同。
首先安裝一個(gè)插件:
$ npm install --save-dev babel-plugin-transform-es2015-classes
然后將 plugins 字段添加到您的 .babelrc 中。
{
+ "plugins": [
+ "transform-es2015-classes"
+ ]
}
這使您可以更精確地控制正在運(yùn)行的確切的 transforms 。
有關(guān)官方插件的完整列表,請(qǐng)參見(jiàn)Babel插件頁(yè)面[6]。
還請(qǐng)看一下社區(qū)構(gòu)建的所有插件[7]。如果您想學(xué)習(xí)如何編寫(xiě)自己的插件,請(qǐng)閱讀Babel插件手冊(cè)[8](圖雀社區(qū)將在之后翻譯這本插件手冊(cè),敬請(qǐng)期待~)。
插件選項(xiàng)
許多插件還具有將其配置為不同行為的 option 。例如,許多 transform 都具有 loose 模式,該模式會(huì)放棄某些規(guī)范行為,而傾向于使用更簡(jiǎn)單,性能更高的代碼。
要將選項(xiàng)添加到插件,只需進(jìn)行以下更改:
{
"plugins": [
- "transform-es2015-classes"
+ ["transform-es2015-classes", { "loose": true }]
]
}
根據(jù)環(huán)境定制 Babel
Babel插件解決了許多不同的任務(wù)。其中許多是開(kāi)發(fā)工具,可以幫助您調(diào)試代碼或與工具集成。還有許多用于優(yōu)化生產(chǎn)中代碼的插件。
因此,通常需要基于環(huán)境的 Babel 配置。您可以使用 .babelrc 文件輕松完成此操作。
{
"presets": ["es2015"],
"plugins": [],
+ "env": {
+ "development": {
+ "plugins": [...]
+ },
+ "production": {
+ "plugins": [...]
+ }
}
}
Babel將根據(jù)當(dāng)前環(huán)境在 env 內(nèi)部啟用配置。
當(dāng)前環(huán)境將使用 process.env.BABEL_ENV 。當(dāng) BABEL_ENV 不可用時(shí),它將回退到 NODE_ENV ,如果不可用,則默認(rèn)為“ development ”。
Unix
$ BABEL_ENV=production [COMMAND]
$ NODE_ENV=production [COMMAND]
Windows
$ SET BABEL_ENV=production
$ [COMMAND]
注意:
[COMMAND]是您用來(lái)運(yùn)行Babel的任何東西(即babel,babel-node,或者如果您正在使用babel-register鉤子,則可能只是node)。
提示:如果要讓命令在 Unix 和 Windows 跨平臺(tái)上運(yùn)行,請(qǐng)使用 cross-env[9]。
構(gòu)建自己的預(yù)設(shè)
手動(dòng)指定插件?插件選項(xiàng)?基于環(huán)境的設(shè)置?對(duì)于所有項(xiàng)目,所有這些配置似乎都需要重復(fù)很多次。
因此,我們鼓勵(lì)社區(qū)創(chuàng)建自己的預(yù)設(shè)。這可以是您整個(gè)公司[10]的預(yù)設(shè)。
創(chuàng)建預(yù)設(shè)很容易。假設(shè)您有以下 .babelrc 文件:
{
"presets": [
"es2015",
"react"
],
"plugins": [
"transform-flow-strip-types"
]
}
您需要做的就是按照命名約定 babel-preset-* 創(chuàng)建一個(gè)新項(xiàng)目(請(qǐng)對(duì)此命名空間負(fù)責(zé)!),并創(chuàng)建兩個(gè)文件。
首先,創(chuàng)建一個(gè)新的 package.json 文件,該文件具有您的預(yù)設(shè)所需的 dependencies 關(guān)系。
{
"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"
}
}
然后創(chuàng)建一個(gè) index.js 文件,該文件導(dǎo)出 .babelrc 文件的內(nèi)容,并用 require 調(diào)用替換插件/預(yù)設(shè)字符串。
module.exports = {
presets: [
require("babel-preset-es2015"),
require("babel-preset-react")
],
plugins: [
require("babel-plugin-transform-flow-strip-types")
]
};
然后只需將其發(fā)布到 npm,就可以像使用任何預(yù)設(shè)一樣使用它。
Babel 和其他工具結(jié)合
一旦掌握了 Babel,Babel 便會(huì)很直接地進(jìn)行設(shè)置,但是使用其他工具進(jìn)行設(shè)置可能非常困難。但是,我們嘗試與其他項(xiàng)目緊密合作,以使體驗(yàn)盡可能輕松。
靜態(tài)分析工具
較新的標(biāo)準(zhǔn)為語(yǔ)言帶來(lái)了許多新語(yǔ)法,而靜態(tài)分析工具才剛剛開(kāi)始利用它。
Linting
ESLint 是最受歡迎的 Lint 工具之一,因此,我們維護(hù)了官方的 babel-eslint[11] 集成。首先安裝 eslint 和 babel-eslint 。
$ npm install --save-dev eslint babel-eslint
接下來(lái),在項(xiàng)目中創(chuàng)建或使用現(xiàn)有的 .eslintrc 文件,并將解析器設(shè)置為 babel-eslint 。
{
+ "parser": "babel-eslint",
"rules": {
...
}
}
現(xiàn)在將一個(gè) lint 任務(wù)添加到您的 npm package.json 腳本中:
{
"name": "my-module",
"scripts": {
+ "lint": "eslint my-files.js"
},
"devDependencies": {
"babel-eslint": "...",
"eslint": "..."
}
}
然后只需運(yùn)行任務(wù)即可完成所有設(shè)置。
$ npm run lint
有關(guān)更多信息,請(qǐng)查閱 babel-eslint[12]或eslint[13]文檔。
文檔
使用Babel,ES2015和Flow,您可以推斷出很多有關(guān)您的代碼的信息。使用documentation.js[14],您可以非常輕松地生成詳細(xì)的API文檔。
Documentation.js在后臺(tái)使用Babel支持所有最新語(yǔ)法,包括Flow注釋,以便在代碼中聲明類型。
框架
現(xiàn)在,所有主要的JavaScript框架都專注于圍繞語(yǔ)言的未來(lái)調(diào)整其API。因此,在工具中進(jìn)行了大量工作。
框架不僅有機(jī)會(huì)使用Babel,而且有機(jī)會(huì)以改善用戶體驗(yàn)的方式對(duì)其進(jìn)行擴(kuò)展。
React
React極大地改變了其API以使其與ES2015類保持一致(在此處了解更新的API)。更進(jìn)一步,React依賴Babel來(lái)編譯它的JSX語(yǔ)法,不贊成Babel來(lái)使用它自己的自定義工具。您可以按照上述說(shuō)明開(kāi)始設(shè)置 babel-preset-react 程序包。
React社區(qū)接受了Babel并與之合作。社區(qū)[15]現(xiàn)在進(jìn)行了許多轉(zhuǎn)換。
最著名的是 babel-plugin-react-transform 插件,結(jié)合了許多特定于 React 的轉(zhuǎn)換,可以啟用熱模塊重裝和其他調(diào)試實(shí)用程序。
參考資料
交互式設(shè)置頁(yè)面: 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插件頁(yè)面: http://babeljs.io/docs/plugins/
[7]所有插件: https://www.npmjs.com/search?q=babel-plugin
[8]Babel插件手冊(cè): 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]社區(qū): https://www.npmjs.com/search?q=babel-plugin+react
