Babel 工具鏈?zhǔn)怯纱罅康墓ぞ呓M成的,無論你是 “最終用戶” 還是在集成 Babel,這些工具都簡化了 Babel 的使用。本文是對這些工具的使用方法的快速介紹,你可以在文檔的 “用法” 章節(jié)了解到更多信息。
如果你正在使用的是一套框架,Babel 的配置可能會有所不同,也可能已經(jīng)自動為你配置好了。
本指南將想你展示如何將 ES2015+ 語法的 JavaScript 代碼編譯為能在當(dāng)前瀏覽器上工作的代碼。這將涉及到新語法的轉(zhuǎn)換和缺失特性的修補(bǔ)。
整個配置過程包括:
//npm命令
npm install --save-dev @babel/core @babel/cli @babel/preset-env
//Yarn命令
yarn add --dev @babel/core @babel/cli @babel/preset-env
//pnpm命令
pnpm add --save-dev @babel/core @babel/cli @babel/preset-env
babel.config.json
的配置文件(需要 v7.8.0
或更高版本),并將以下內(nèi)容復(fù)制到此文件中:
{
"presets": [
[
"@babel/preset-env",
{
"targets": {
"edge": "17",
"firefox": "60",
"chrome": "67",
"safari": "11.1"
},
"useBuiltIns": "usage",
"corejs": "3.6.5"
}
]
]
}
上述瀏覽器列表僅用于示例。請根據(jù)你所需要支持的瀏覽器進(jìn)行調(diào)整。參見 此處 以了解
@babel/preset-env
可接受哪些參數(shù)。
如果你使用的是 Babel 的舊版本,則文件名為 babel.config.js
。
babel.config.js
const presets = [
[
"@babel/preset-env",
{
targets: {
edge: "17",
firefox: "60",
chrome: "67",
safari: "11.1",
},
useBuiltIns: "usage",
corejs: "3.6.4",
},
],
];
module.exports = { presets };
src
目錄下的所有代碼編譯到 lib
目錄:
./node_modules/.bin/babel src --out-dir lib
你可以利用 npm@5.2.0 所自帶的 npm 包運(yùn)行器將
./node_modules/.bin/babel
命令縮短為npx babel
繼續(xù)閱讀后面的分步講解,了解其工作原理以及每個工具的功能。
@babel
作為冠名的。這種模塊化的設(shè)計(jì)能夠讓每種工具都針對特定使用情況進(jìn)行設(shè)計(jì)。 下面我們著重看一下 @babel/core
和 @babel/cli
。Babel 的核心功能包含在 @babel/core 模塊中。通過以下命令安裝:
//npm命令
npm install --save-dev @babel/core
//Yarn命令
yarn add --dev @babel/core
//pnpm命令
pnpm add --save-dev @babel/core
require
并使用它:JavaScript
const babel = require("@babel/core");
babel.transformSync("code", optionsObject);
作為一名最終用戶,你可以還需要安裝其他工具作為 @babel/core
的使用接口并很好地集成到你的開發(fā)流程中。即便如此,你仍然需要查看其文檔并了解可用的參數(shù),其中很多參數(shù)也可以通過其他工具進(jìn)行設(shè)置。
@babel/cli 是一個能夠從終端(命令行)使用的工具。下面是其安裝命令和基本用法:
//npm命令
npm install --save-dev @babel/core @babel/cli
./node_modules/.bin/babel src --out-dir lib
//Yarn命令
yarn add --dev @babel/core @babel/cli
./node_modules/.bin/babel src --out-dir lib
//pnpm命令
pnpm add --save-dev @babel/core @babel/cli
./node_modules/.bin/babel src --out-dir lib
這將解析 ?src
?目錄下的所有 JavaScript 文件,并應(yīng)用我們所指定的代碼轉(zhuǎn)換功能,然后把每個文件輸出到 ?lib
? 目錄下。由于我們還沒有指定任何代碼轉(zhuǎn)換功能,所以輸出的代碼將與輸入的代碼相同(不保留原代碼格式)。我們可以將我們所需要的代碼轉(zhuǎn)換功能作為參數(shù)傳遞進(jìn)去。
上面的示例中我們使用了 ?--out-dir
? 參數(shù)。你可以通過? --help
?參數(shù)來查看命令行工具所能接受的所有參數(shù)列表。但是現(xiàn)在對我們來說最重要的是 ?--plugins
?和 ?--presets
?這兩個參數(shù)。
代碼轉(zhuǎn)換功能以插件的形式出現(xiàn),插件是小型的 JavaScript 程序,用于指導(dǎo) Babel 如何對代碼進(jìn)行轉(zhuǎn)換。你甚至可以編寫自己的插件將你所需要的任何代碼轉(zhuǎn)換功能應(yīng)用到你的代碼上。例如將 ES2015+ 語法轉(zhuǎn)換為 ES5 語法,我們可以使用諸如 ?@babel/plugin-transform-arrow-functions
?之類的官方插件:
//npm命令
npm install --save-dev @babel/plugin-transform-arrow-functions
./node_modules/.bin/babel src --out-dir lib --plugins=@babel/plugin-transform-arrow-functions
//Yarn命令
yarn add --dev @babel/plugin-transform-arrow-functions
./node_modules/.bin/babel src --out-dir lib --plugins=@babel/plugin-transform-arrow-functions
//pnpm命令
pnpm add --save-dev @babel/plugin-transform-arrow-functions
./node_modules/.bin/babel src --out-dir lib --plugins=@babel/plugin-transform-arrow-functions
JavaScript
const fn = () => 1;
// converted to
var fn = function fn() {
return 1;
};
這是個好的開始!但是我們的代碼中仍然殘留了其他 ES2015+ 的特性,我們希望對它們也進(jìn)行轉(zhuǎn)換。我們不需要一個接一個地添加所有需要的插件,我們可以使用一個 "preset" (即一組預(yù)先設(shè)定的插件)。
就像插件一樣,你也可以根據(jù)自己所需要的插件組合創(chuàng)建一個自己的 preset 并將其分享出去。J對于當(dāng)前的用例而言,我們可以使用一個名稱為 ?env
?的 preset。
//npm命令
npm install --save-dev @babel/preset-env
./node_modules/.bin/babel src --out-dir lib --presets=@babel/env
//Yarn命令
yarn add --dev @babel/preset-env
./node_modules/.bin/babel src --out-dir lib --presets=@babel/env
//pnpm命令
pnpm add --save-dev @babel/preset-env
./node_modules/.bin/babel src --out-dir lib --presets=@babel/env
如果不進(jìn)行任何配置,上述 preset 所包含的插件將支持所有最新的 JavaScript (ES2015、ES2016 等)特性。但是 preset 也是支持參數(shù)的。我們來看看另一種傳遞參數(shù)的方法:配置文件,而不是通過終端控制臺同時傳遞 cli 和 preset 的參數(shù)。
根據(jù)你的需要,可以通過幾種不同的方式來使用配置文件。另外,請務(wù)必閱讀我們關(guān)于如何 配置 Babel 的深入指南以了解更多信息。
現(xiàn)在,我們首先創(chuàng)建一個名為 babel.config.json
的文件(需要 v7.8.0
或更高版本),并包含如下內(nèi)容:
{
"presets": [
[
"@babel/preset-env",
{
"targets": {
"edge": "17",
"firefox": "60",
"chrome": "67",
"safari": "11.1"
}
}
]
]
}
env
的 preset 只會為目標(biāo)瀏覽器中沒有的功能加載轉(zhuǎn)換插件。語法都已經(jīng)清楚了,接下來我們看看 polyfills 。 從 Babel 7.4.0 版本開始,這個軟件包已經(jīng)不建議使用了,建議直接包含 core-js/stable
(用于模擬 ECMAScript 的功能):
JavaScript
import "core-js/stable";
如果您正在將生成器或異步函數(shù)編譯到ES5,并且您使用的是7.18.0之前的?@babel/core
?或?@babel/plugin-transformat-regenerator
?版本,則還必須加載 regenerator runtime
包。當(dāng)使用?@babel/preset-env的useBuiltIns:“usage”
?選項(xiàng)或@babel/plugin-transform-runtime
,它會自動加載。
@babel/polyfill 模塊包含 core-js 和一個自定義的 regenerator runtime 來模擬完整的 ES2015+ 環(huán)境。
這意味著你可以使用諸如 Promise
和 WeakMap
之類的新的內(nèi)置組件、 Array.from
或 Object.assign
之類的靜態(tài)方法、 Array.prototype.includes
之類的實(shí)例方法以及生成器函數(shù)(generator functions)(前提是你使用了 regenerator 插件)。為了添加這些功能,polyfill 將添加到全局范圍(global scope)和類似 String
這樣的原生原型(native prototypes)中。
對于軟件庫/工具的作者來說,這可能太多了。如果你不需要類似 Array.prototype.includes 的實(shí)例方法,可以使用 transform runtime 插件而不是對全局范圍(global scope)造成污染的 @babel/polyfill。
更進(jìn)一步,如果你確切地指導(dǎo)你所需要的 polyfills 功能,你可以直接從 core-js 獲取它們。
由于我們構(gòu)建的是一個應(yīng)用程序,因此我們只需安裝 @babel/polyfill
即可:
//npm 命令
npm install --save @babel/polyfill
//Yarn命令
yarn add @babel/polyfill
//pnpm命令
pnpm add @babel/polyfill
注意,使用
--save
參數(shù)而不是--save-dev
,因?yàn)檫@是一個需要在你的源碼之前運(yùn)行的 polyfill。
幸運(yùn)的是,我們所使用的 env
preset 提供了一個 "useBuiltIns"
參數(shù),當(dāng)此參數(shù)設(shè)置為 "usage"
時,就會加載上面所提到的最后一個優(yōu)化措施,也就是只包含你所需要的 polyfill。使用此新參數(shù)后,修改配置如下:
babel.config.json
{
"presets": [
[
"@babel/preset-env",
{
"targets": {
"edge": "17",
"firefox": "60",
"chrome": "67",
"safari": "11.1"
},
"useBuiltIns": "usage"
}
]
]
}
Babel 將檢查你的所有代碼,以便查找目標(biāo)環(huán)境中缺失的功能,然后只把必須的 polyfill 包含進(jìn)來。示例代碼如下:
JavaScript
Promise.resolve().finally();
將被轉(zhuǎn)換為(由于 Edge 17 沒有 Promise.prototype.finally
):
JavaScript
require("core-js/modules/es.promise.finally");
Promise.resolve().finally();
如果我們不使用將 "useBuiltIns" 參數(shù)設(shè)置為 "usage" (默認(rèn)值是 "false")的 env 預(yù)設(shè)的話,那么我們必須在所有代碼之前利用 require 加載 一次 完整的 polyfill。
例如:
babel.config.json
{
"presets": [
[
"@babel/preset-env",
{
"targets": {
"edge": "17",
"firefox": "60",
"chrome": "67",
"safari": "11.1"
},
"useBuiltIns": "entry"
}
]
]
}
然后首先導(dǎo)入 core-js(到polyfill ECMAScript功能),在我們的入口文件中模擬完整的ES2015+環(huán)境,因?yàn)?a href="http://m.o2fo.com/babel/babelpolyfill.html" target="_blank">@pabel/polyfill已經(jīng)被棄用:
JavaScript
import "core-js/stable";
我們使用 @babel/cli 從終端運(yùn)行 Babel,利用 @babel/polyfill 來模擬所有新的 JavaScript 功能,而 env preset 只對我們所使用的并且目標(biāo)瀏覽器中缺失的功能進(jìn)行代碼轉(zhuǎn)換和加載 polyfill。
更多建議: