升級至 Babel 7
升級至 Babel 7 時,請將使用者導向此文件。請按此查看 API/整合變更。
由於並非每個重大變更都會影響每個專案,因此我們已按變更升級時中斷測試的可能性對各章節進行排序。
所有 Babel
我們強烈建議您使用較新的 Node.js 版本 (LTS v8),因為舊版本不再維護。請參閱 nodejs/LTS 以取得更多資訊。
這只表示 Babel 本身 無法在舊版 Node 上執行。它仍可輸出在舊版 Node 上執行的程式碼。
設定查詢變更
如需更多資訊,請閱讀我們的 6.x 與 7.x 比較。
Babel 以前在處理 node_modules
、符號連結和單一存放庫時曾發生問題。我們已針對此問題進行了一些變更:Babel 將停止在 package.json
邊界查詢,而不是向上查詢。對於單一存放庫,我們新增了新的 babel.config.js
檔案,將所有套件的設定集中起來(您也可以為每個套件建立設定)。在 7.1 中,我們引入了 rootMode
選項,以在必要時進一步查詢。
年度預設已棄用
「env」預設已推出超過一年,且完全取代了我們之前擁有和建議的一些預設。
babel-preset-es2015
babel-preset-es2016
babel-preset-es2017
babel-preset-latest
- 上述 ^ 的組合
這些預設值應以「env」預設值取代。
階段預設值已棄用
我們將移除階段預設值,改用明確的提案用法。可以查看 stage-0 自述檔 以取得更多移轉步驟。
若要自動執行此步驟,您可以執行 npx babel-upgrade
(已在此處新增公關 連結)。
移除 @babel/polyfill
中的提案多載
基於類似的考量,我們已從 @babel/polyfill
中移除多載提案。
目前,@babel/polyfill
主要只是 core-js
v2 的別名。來源
在過去,它只會是 2 個匯入
import "core-js/shim"; // included < Stage 4 proposals
import "regenerator-runtime/runtime";
如果您想要使用提案,您需要獨立匯入這些提案。您應直接從 core-js
套件或 npm 上的其他套件匯入這些提案。
例如
// for core-js v2:
import "core-js/fn/array/flat-map";
// for core-js v3:
import "core-js/features/array/flat-map";
以下是 core-js
v2 中階段 < 3 提案多載的清單。
詳細資料
// core-js v2
// Stage 3
import "core-js/fn/string/trim-left";
import "core-js/fn/string/trim-right";
import "core-js/fn/string/match-all";
import "core-js/fn/array/flat-map";
import "core-js/fn/array/flatten"; // RENAMED
import "core-js/fn/global";
// Stage 1
import "core-js/fn/symbol/observable";
import "core-js/fn/promise/try";
import "core-js/fn/observable";
// Stage 1 Math Extensions
import "core-js/fn/math/clamp";
import "core-js/fn/math/deg-per-rad";
import "core-js/fn/math/degrees";
import "core-js/fn/math/fscale";
import "core-js/fn/math/iaddh";
import "core-js/fn/math/isubh";
import "core-js/fn/math/imulh";
import "core-js/fn/math/rad-per-deg";
import "core-js/fn/math/radians";
import "core-js/fn/math/scale";
import "core-js/fn/math/umulh";
import "core-js/fn/math/signbit";
// Stage 1 "of and from on collection constructors"
import "core-js/fn/map/of";
import "core-js/fn/set/of";
import "core-js/fn/weak-map/of";
import "core-js/fn/weak-set/of";
import "core-js/fn/map/from";
import "core-js/fn/set/from";
import "core-js/fn/weak-map/from";
import "core-js/fn/weak-set/from";
// Stage 0
import "core-js/fn/string/at";
// Nonstandard
import "core-js/fn/object/define-getter";
import "core-js/fn/object/define-setter";
import "core-js/fn/object/lookup-getter";
import "core-js/fn/object/lookup-setter";
// import "core-js/fn/map/to-json"; // Not available standalone
// import "core-js/fn/set/to-json"; // Not available standalone
import "core-js/fn/system/global";
import "core-js/fn/error/is-error";
import "core-js/fn/asap";
// Decorator metadata? Not sure of stage/proposal
import "core-js/fn/reflect/define-metadata";
import "core-js/fn/reflect/delete-metadata";
import "core-js/fn/reflect/get-metadata";
import "core-js/fn/reflect/get-metadata-keys";
import "core-js/fn/reflect/get-own-metadata";
import "core-js/fn/reflect/get-own-metadata-keys";
import "core-js/fn/reflect/has-metadata";
import "core-js/fn/reflect/has-own-metadata";
import "core-js/fn/reflect/metadata";
版本化/相依性
大部分的套件/頂層套件現在對 @babel/core
有 peerDependency
。
套件重新命名
babylon
現在是@babel/parser
你仍然可以在設定檔中使用套件名稱的簡寫版本(移除 preset-
或 plugin-
),但我選擇使用完整的套件名稱以求清楚(也許我們應該直接移除它,因為它並沒有省下多少輸入)。
{
- "presets": ["@babel/preset-react"],
+ "presets": ["@babel/react"], // this is equivalent
- "plugins": ["@babel/transform-runtime"],
+ "plugins": ["@babel/plugin-transform-runtime"], // same
}
範圍套件
最重要的變更終於是將所有套件切換到 範圍套件(單一存放庫 中資料夾名稱沒有變更,但其 package.json
中的名稱有變更)。
這表示將不再有意外/故意的名稱搶註問題,與社群套件有明確的區分,以及更簡單的命名慣例。
你的相依性需要修改如下
babel-cli
-> @babel/cli
。對我們來說,我們基本上從用 @babel/
取代 babel-
開始。
在設定檔中使用
你仍然可以使用簡寫方式指定預設或套件。不過因為切換到範圍套件,你仍然必須指定 @babel/
,就像你要將自己的預設新增到設定檔一樣。
module.exports = {
presets: ["@babel/env"], // "@babel/preset-env"
plugins: ["@babel/transform-arrow-functions"], // same as "@babel/plugin-transform-arrow-functions"
};
切換至 TC39 提議的 -proposal-
這表示任何不在年度版本(ES2015、ES2016 等)中的外掛程式都應重新命名為 -proposal
。這樣我們才能更清楚地表示提議並未正式納入 JavaScript。
範例
@babel/plugin-transform-function-bind
現為@babel/plugin-proposal-function-bind
(第 0 階段)@babel/plugin-transform-class-properties
現為@babel/plugin-proposal-class-properties
(第 3 階段)
這也表示當提議移至第 4 階段時,我們應重新命名套件。
從套件名稱中移除年份
有些外掛程式名稱中含有 -es3-
或 -es2015-
,但這些都是不必要的。
@babel/plugin-transform-es2015-classes
已變更為 @babel/plugin-transform-classes
。
CommonJS 中的 "use strict"
和 this
Babel 6 的 ES6 模組轉換會不分青紅皂白地執行在任何被告知要處理的檔案上,從未考慮檔案中是否實際包含 ES6 匯入/匯出。這會將檔案範圍的 this
參考重寫為 undefined
,並在 Babel 處理的所有 CommonJS 模組最上方插入 "use strict"
。
// input.js
this;
// output.js v6
"use strict"; // assumed strict modules
undefined; // changed this to undefined
// output.js v7
this;
此行為已在 Babel 7 中受到限制,因此對於 transform-es2015-modules-commonjs
轉換,檔案僅在檔案中具有 ES6 匯入或匯出時才會變更。(編輯註解:如果我們登入 https://github.com/babel/babel/issues/6242,這可能會再次變更,因此我們會希望在發布前重新檢視這一點)。
// input2.js
import "a";
// output.js v6 and v7
"use strict";
require("a");
如果您依賴 Babel 自動將 "use strict"
注入所有 CommonJS 模組,您會希望在 Babel 設定中明確使用 transform-strict-mode
外掛程式。
React 和 Flow 預設值的區分
babel-preset-react
一直都包含 flow 外掛程式。這已造成許多問題,使用者會因為拼字錯誤而意外使用 flow
語法,或在未以 flow
本身進行類型檢查的情況下將其加入,導致錯誤。
當我們決定支援 TypeScript 時,這個問題變得更為複雜。如果您想要使用 React 和 TypeScript 預設值,我們必須找出一個方法,自動透過檔案類型或指令開啟/關閉語法。最後,將預設值完全區分開來會比較容易。
預設值讓 Babel 能夠剖析 Flow / TypeScript(以及其他方言/語言)提供的類型,然後在編譯成 JavaScript 時將其移除。
{
- "presets": ["@babel/preset-react"]
+ "presets": ["@babel/preset-react", "@babel/preset-flow"] // parse & remove flow types
+ "presets": ["@babel/preset-react", "@babel/preset-typescript"] // parse & remove typescript types
}
選項剖析
Babel 的設定選項比 Babel 6 更加嚴格。對於預設值的逗號分隔清單,例如 "presets": 'es2015, es2016'
在技術上之前有效,現在會失敗,且需要變更為陣列 #5463。
請注意,這不適用於 CLI,其中 --presets es2015,es2016
肯定仍然有效。
{
- "presets": "@babel/preset-env, @babel/preset-react"
+ "presets": ["@babel/preset-env", "@babel/preset-react"]
}
外掛/預設匯出
所有外掛/預設現在應匯出函式,而非物件,以保持一致性 (經由 babel/babel#6494)。這有助於我們進行快取。
解析基於字串的設定值
在 Babel 6 中,傳遞給 Babel 的值(非來自設定檔),會相對於正在編譯的檔案解析,這導致許多混淆。
在 Babel 7 中,值會一致地相對於載入它們的設定檔,或相對於工作目錄解析。
對於 presets
和 plugins
值,此變更表示 CLI 在下列情況下會表現良好
babel --presets @babel/preset-env ../file.js
假設您的 node_modules
資料夾在 .
中,在 Babel 6 中,這會失敗,因為找不到預設。
此變更也影響 only
和 ignore
,這將在接下來進行擴充。
基於路徑的 only
和 ignore
模式
在 Babel 6 中,only
和 ignore
被視為一般比對字串,而非檔案路徑萬用字元。這表示例如 *.foo.js
會比對 ./**/*.foo.js
,這對大多數使用者來說令人困惑且驚訝。
在 Babel 7 中,這些現在被視為路徑為基礎的 glob 模式,可以是相對路徑或絕對路徑。這表示如果您使用這些模式,您可能至少需要在它們前面加上 **/
前綴,以確保您的模式深入匹配目錄。
only
和 ignore
模式仍然也適用於目錄,因此您也可以使用 only: './tests'
來僅編譯 tests
目錄中的檔案,而無需使用 **/*.js
來匹配所有巢狀檔案。
Babel 的 CLI 命令
babel
命令的 --copy-files
參數,告訴 Babel 複製 Babel 不知道如何處理的目錄中的所有檔案,現在也會複製未通過 only
/ignore
檢查的檔案,而之前會靜默略過所有忽略的檔案。
@babel/node
Babel 6 中的 babel-node
命令是 babel-cli
套件的一部分。在 Babel 7 中,此命令已拆分為其自己的 @babel/node
套件,因此如果您使用該命令,您需要新增此新相依性。
@babel/runtime
、@babel/plugin-transform-runtime
我們已將 Babel 的輔助程式從其執行階段的「polyfilling」行為中分離出來。更多詳細資訊請參閱 PR。
@babel/runtime
現在僅包含輔助程式,如果您需要 core-js
,可以使用 @babel/runtime-corejs2
和轉換中提供的選項。對於這兩個,您仍然需要 @babel/plugin-transform-runtime
僅輔助程式
# install the runtime as a dependency
npm install @babel/runtime
# install the plugin as a devDependency
npm install @babel/plugin-transform-runtime --save-dev
{
"plugins": ["@babel/plugin-transform-runtime"]
}
輔助程式 + 來自 core-js
的多重填補
因此,如果您需要 core-js
支援 transform-runtime
,現在您將傳遞 corejs
選項,並使用 @babel/runtime-corejs2
相依性,而非 @babel/runtime
。
# install the runtime as a dependency
npm install @babel/runtime-corejs2
# install the plugin as a devDependency
npm install @babel/plugin-transform-runtime --save-dev
{
"plugins": [
- ["@babel/plugin-transform-runtime"],
+ ["@babel/plugin-transform-runtime", {
+ "corejs": 2,
+ }],
]
}
規範相容性
@babel/plugin-proposal-object-rest-spread
尾隨逗號不能出現在物件中的 RestElement 之後 #290
var {
- ...y, // trailing comma is a SyntaxError
+ ...y
} = { a: 1 };
由於物件散佈定義了新屬性,而
Object.assign
僅設定它們,因此 Babel 已將預設行為變更為更符合規範。
// input
z = { x, ...y };
// v7 default behavior: ["proposal-object-rest-spread"]
function _objectSpread(target) { ... }
z = _objectSpread({
x
}, y);
// Old v6 behavior: ["proposal-object-rest-spread", { "loose": true }]
function _extends(target) { ... }
z = _extends({
x
}, y);
// Substitute for Object.assign: ["proposal-object-rest-spread", { "loose": true, "useBuiltIns": true }]
z = Object.assign(
{
x,
},
y
);
@babel/plugin-proposal-class-properties
預設行為已變更為之前預設的「規範」
// input
class Bork {
static a = "foo";
y;
}
// v7 default behavior: ["@babel/plugin-proposal-class-properties"]
var Bork = function Bork() {
Object.defineProperty(this, "y", {
enumerable: true,
writable: true,
value: void 0,
});
};
Object.defineProperty(Bork, "a", {
enumerable: true,
writable: true,
value: "foo",
});
// old v6 behavior: ["@babel/plugin-proposal-class-properties", { "loose": true }]
var Bork = function Bork() {
this.y = void 0;
};
Bork.a = "foo";
將 @babel/plugin-transform-export-extensions
分割成兩個重新命名的提案
這是期待已久的事情,但終於變更了。
@babel/plugin-proposal-export-default-from
export v from "mod";
@babel/plugin-proposal-export-namespace-from
export * as ns from "mod";
@babel/plugin-transform-template-literals
範本字串修正已更新 #5523
請參閱 範本字串修正 提案。
它導致 Babel 6 拋出 Bad character escape sequence (5:6)
。
tag`\unicode and \u{55}`;
此問題已在 Babel 7 中修復,並會產生類似以下的內容
// default
function _taggedTemplateLiteral(strings, raw) {
return Object.freeze(
Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })
);
}
var _templateObject = /*#__PURE__*/ _taggedTemplateLiteral(
[void 0],
["\\unicode and \\u{55}"]
);
tag(_templateObject);
// loose mode
function _taggedTemplateLiteralLoose(strings, raw) {
strings.raw = raw;
return strings;
}
var _templateObject = /*#__PURE__*/ _taggedTemplateLiteralLoose(
[void 0],
["\\unicode and \\u{55}"]
);
tag(_templateObject);
預設為一般範本字串的先前「規格」模式
// input
`foo${bar}`;
// default v7 behavior: ["@babel/plugin-transform-template-literals"]
"foo".concat(bar);
// old v6 behavior: ["@babel/plugin-transform-template-literals", { "loose": true }]
"foo" + bar;
@babel/plugin-proposal-decorators
為了預期新的裝飾器提案實作,我們已決定將其設為新的預設行為。這表示若要繼續使用目前的裝飾器語法/行為,您必須將 legacy
選項設為 true
。
{
"plugins": [
- "@babel/plugin-proposal-decorators"
+ ["@babel/plugin-proposal-decorators", { "legacy": true }]
]
}
注意:如果您使用包含此外掛程式的
@babel/preset-stage-0
或@babel/preset-stage-1
,您必須傳遞decoratorsLegacy
選項給它們。
@babel/plugin-proposal-pipeline-operator
預設情況下,較新的提案會出錯,且在提案仍為 < 第 2 階段時,會要求所有人選擇特定的提案。這篇文章 中有更詳細的說明。
{
"plugins": [
- "@babel/plugin-proposal-pipeline-operator"
+ ["@babel/plugin-proposal-pipeline-operator", { "proposal": "minimal" }]
]
}
已移除 babel-plugin-transform-class-constructor-call
babel-plugin-transform-class-constructor-call 已移除 #5119
TC39 決定放棄此提案。您可以將邏輯移至建構函式或靜態方法中。
請參閱 /docs/plugins/transform-class-constructor-call/ 以取得更多資訊。
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
- call constructor(x, y) {
+ static secondConstructor(x, y) {
return new Point(x, y);
}
}
let p1 = new Point(1, 2);
- let p2 = Point(3, 4);
+ let p2 = Point.secondConstructor(3, 4);
@babel/plugin-async-to-generator
我們已將 babel-plugin-transform-async-to-module-method
合併至一般非同步外掛程式,只需將其設為選項即可。
{
"plugins": [
- ["@babel/transform-async-to-module-method"]
+ ["@babel/transform-async-to-generator", {
+ "module": "bluebird",
+ "method": "coroutine"
+ }]
]
}
babel
放棄
babel
套件 #5293
此套件目前會提供錯誤訊息,要求您在 v6 中安裝 babel-cli
。不過,我認為我們可以針對此名稱做一些有趣的事情。
@babel/register
已移除
babel-core/register.js
#5132
babel-core/register
的已棄用用法已在 Babel 7 中移除;請改用獨立套件 @babel/register
。
將 @babel/register
安裝為新的相依性
- npm
- Yarn
- pnpm
npm install --save-dev @babel/register
yarn add --dev @babel/register
pnpm add --save-dev @babel/register
使用 Mocha 升級
- mocha --require babel-core/register
+ mocha --require @babel/register
@babel/register
現在也只會編譯當前工作目錄中的檔案(此變更旨在修復符號連結的問題)。
@babel/register
選項現在會取代,而不是合併
@babel/generator
移除
quotes
選項 #5154]
如果您想要編譯輸出的格式,可以使用 recast/prettier/escodegen/fork babel-generator。
此選項僅能透過 babel-generator
明確使用,直到 v6.18.0,當時我們公開了 parserOpts
和 generatorOpts
。由於該版本中有一個錯誤,因此沒有人應該在 Babel 本身中使用此選項。
移除
flowUsesCommas
選項 #5123
目前 Flow 物件類型中支援 2 種語法(,
和 ;
)。
此變更僅讓 babel-generator 輸出 ,
,而不是 ;
。
@babel/core
移除
babel-core/src/api/browser.js
#5124
babel-browser
已在 6.0 中移除。如果你需要在瀏覽器或非 Node 環境中使用 Babel,請使用 @babel/standalone。
Babel 會將 filename
回傳為絕對路徑 #8044
@babel/preset-env
loose
模式現在會自動排除 typeof-symbol
轉換(許多使用 loose 模式的專案都這麼做)。