Babel 是 Web 開發者工具箱中令人驚艷的一員。它是一個很棒的工具,已經存在很長一段時間,但現在幾乎每個 JavaScript 開發者都依賴它,這種情況還會持續,因為 Babel 現在不可或缺,並為所有人解決了一個大問題。
本文介紹的是 Babel 7,目前的穩定版本。
Babel 簡介
Babel 是一個很棒的工具,已經存在很長一段時間,但現在幾乎每個 JavaScript 開發者都依賴它,這種情況還會持續,因為 Babel 現在不可或缺,並為所有人解決了一個大問題。
哪個問題?
這是每個 Web 開發者肯定都遇到過的問題:JavaScript 的某個特性在最新版本的瀏覽器中可用,但在舊版本中卻不行。或者 Chrome 或 Firefox 實現了它,但 Safari iOS 和 Edge 卻沒有。
例如,ES6 引入了箭頭函數:
[1, 2, 3].map((n) => n + 1)
這在現代瀏覽器中都有支持。但 IE11 不支持它,也不支持 Opera Mini(怎么知道的?通過檢查 ES6 兼容性表)。
那麼你應該如何解決這個問題呢?你是應該放棄那些舊的/不兼容的瀏覽器,還是應該編寫舊的 JavaScript 代碼,讓所有用戶都開心?
這時候,Babel 登場了。Babel 是一個編譯器:它接收一種標準的代碼,將其轉換為另一種標準的代碼。
你可以配置 Babel 將現代 ES2017 JavaScript 轉換為 JavaScript ES5 語法:
[1, 2, 3].map(function(n) {
return n + 1
})
這必須在構建時進行,所以你必須設置一個能夠處理這一過程的工作流。Webpack 是一個常見的解決方案。
(註:如果你對於這個 ES 的東西感到困惑,可以在 ECMAScript 指南 中了解更多有關 ES 版本的信息)
安裝 Babel
使用 npm,在項目中可以輕鬆安裝 Babel:
npm install --save-dev @babel/core @babel/cli
過去我推薦安裝全局的
babel-cli
,但這現在已被 Babel 的維護者不鼓勵使用,因為在每個項目中使用此工具可以在每個項目中擁有不同的 Babel 版本,並且將 Babel 持久化到你的代碼庫更有利於團隊合作。
由於 npm 現在配備了 npx
,在項目文件夾中可以直接輸入命令來運行本地安裝的 CLI 包:
現在我們只需這樣運行 Babel:
npx babel script.js
一個示例 Babel 配置
Babel 默認情況下不會達到任何有用的效果,需要對其進行配置並添加插件。
為了解決我們在介紹中提到的問題(在每個瀏覽器中使用箭頭函數),我們可以運行
npm install --save-dev \
@babel/plugin-transform-arrow-functions
將該包下載到我們應用程序的 node_modules
文件夾中,然後我們需要將
{
"plugins": ["@babel/plugin-transform-arrow-functions"]
}
添加到應用程序根文件夾中的 .babelrc
文件。如果你還沒有該文件,只需創建一個空文件,將內容添加進去。
提示:如果你從未見過以點開頭的文件(以點開頭的文件表示隱藏文件),一開始可能會感到奇怪,因為在你的文件管理器中可能看不到該文件。
現在,如果我們有一個 script.js
文件,其內容如下:
var a = () => {};
var a = (b) => b;
const double = [1,2,3].map((num) => num * 2);
console.log(double); // [2,4,6]
var bob = {
_name: "Bob",
_friends: ["Sally", "Tom"],
printFriends() {
this._friends.forEach(f =>
console.log(this._name + " knows " + f));
}
};
console.log(bob.printFriends());
運行 babel script.js
將輸出以下代碼:
var a = function () {};var a = function (b) {
return b;
};
const double = [1, 2, 3].map(function (num) {
return num * 2;
});console.log(double); // [2,4,6]
var bob = {
_name: "Bob",
_friends: ["Sally", "Tom"],
printFriends() {
var _this = this;
this._friends.forEach(function (f) {
return console.log(_this._name + " knows " + f);
});
}
};
console.log(bob.printFriends());
你可以看到,箭頭函數都已經被轉換為 JavaScript ES5 函數。
Babel 預設
如前一節所述,Babel 可以配置來轉譯特定的 JavaScript 功能。
你可以添加更多插件,但無法逐個功能地添加到配置中,這是不實際的。
這就是 Babel 提供預設的原因。
最受歡迎的預設是 env
和 react
。
提示:Babel 7 廢棄(並移除了)類似
preset-es2017
和 stage 預設,使用@babel/preset-env
替代。
env
預設
env
預設非常好用:你告訴它你要支持的環境,它會為你做好一切,支持所有的現代 JavaScript 功能。
例如:“支持每個瀏覽器的最新的 2 個版本,但是對於 Safari,讓我們支持從 Safari 7 開始的所有版本”。
{
"presets": [
["env", {
"targets": {
"browsers": ["last 2 versions", "safari >= 7"]
}
}]
]
}
或者,“我不需要瀏覽器支持,只需讓我使用 Node.js 6.10”。
{
"presets": [
["env", {
"targets": {
"node": "6.10"
}
}]
]
}
react
預設
react
預設非常方便,可以用於編寫 React 應用:添加 preset-flow
、syntax-jsx
、transform-react-jsx
、transform-react-display-name
。
通過添加這個預設,你可以立即開始開發 React 應用,帶有 JSX 轉換和 Flow 支持。
更多關於預設的資訊
https://babeljs.io/docs/plugins/
使用 Babel 與 webpack
如果你想在瀏覽器中運行現代 JavaScript,僅僅使用 Babel 是不夠的,你還需要將代碼打包。Webpack 是這方面的完美工具。
提示:如果你對 webpack 不熟悉,請閱讀 webpack 指南。
現代 JS 需要兩個不同的階段:編譯階段和運行階段。這是因為一些 ES6+ 功能需要填充或運行時助手。
要安裝 Babel 的填充運行時功能,運行以下命令:
npm install @babel/polyfill \
@babel/runtime \
@babel/plugin-transform-runtime
現在,在你的 webpack.config.js
文件中添加以下內容:
entry: [
'babel-polyfill',
// 你的應用腳本應該放在這裡
],
module: {
loaders: [
// Babel loader 將 ES2015 編譯成 ES5,以實現完全的跨瀏覽器支持
{
loader: 'babel-loader',
test: /\.js$/,
// 只包括在 `src` 子目錄中存在的文件
include: [path.resolve(__dirname, "src")],
// 排除 node_modules,與上一行代碼等效
exclude: /node_modules/,
query: {
// 使用默認的 ES2015 預設,包含所有 ES2015 功能
presets: ['es2015'],
plugins: ['transform-runtime']
}
}
]
}
通過將預設和插件信息放入 webpack.config.js
文件中,我們可以避免使用 .babelrc
文件。