升級到 Babel 7(API)
升級到 Babel 7 時,請將使用者轉介至本文件。
另請參閱 v7-migration 指南,了解其他使用者層級變更。
所有 Babel 套件
NodeJS 支援
已移除對 Node.js 0.10 和 0.12 的支援,因為這兩個版本已停止維護。
匯出變更
已放棄在 Babel 套件上使用 add-module-exports
外掛程式。之前必須使用它來避免我們的匯出發生重大變更。如果你在函式庫中匯入 Babel 套件,在使用 require
而不是 import
時,你可能需要使用 .default
。
@babel/core
已將 ast
預設變更為 false 以提升效能(大多數工具並未使用它)babel/babel#7436。
已移除公開公開但未記載的 Pipeline
類別。最好直接使用 @babel/core
公開的轉換方法babel/babel#5376。
已移除 babel.util.*
輔助方法,且 util.EXTENSIONS
已移至 babel.DEFAULT_EXTENSIONS
babel/babel#5487。
如果檔案符合 ignore
模式或無法符合 only
模式,呼叫 babel.transform
或任何其他轉換函式可能會傳回 null
babel/babel#5487。
已移除 state.file.opts
上公開的 opts.basename
選項。如果你需要它,最好自行從 opts.filename
建立它babel/babel#5467。
已移除 resolveModuleSource
。我們建議使用 babel-plugin-module-resolver@3
的「resolvePath」選項babel/babel#6343。
移除 babel.analyse
,因為它只是 babel.transform
的別名
移除 path.mark()
,因為我們沒有使用它,而且它可以在您自己的外掛程式中實作。
移除 babel.metadata
,因為產生的外掛程式元資料總是包含在輸出結果中。
移除 path.hub.file.addImport
。您可以改用 @babel/helper-module-imports
模組。
+ import { addDefault } from "@babel/helper-module-imports";
function importModule(pkgStore, name, path) {
- return path.hub.file.addImport(resolvePath(pkgStore, name, path), 'default', name);
+ return addDefault(path, resolvePath(pkgStore, name, path), { nameHint: name });
}
設定檔變更
我們對設定檔查詢方式進行了一些重大變更
預設情況下,當為特定檔案搜尋
.babelrc
檔案時,會在package.json
停止。
對於任何特定檔案,Babel v6 會持續查詢目錄階層,直到找到設定檔。這表示您的專案可能會中斷,因為它使用在套件根目錄外部找到的設定檔,例如在主目錄中。
新增支援
babel.config.js
檔案,類似於 Webpack 的作法
由於這會中斷單一存放庫的運作方式(包括 Babel 本身),我們正在引入一個新的設定檔,基本上可以移除設定檔的階層性質。
其中包含一個 root
選項,預設為目前的作業目錄,以便它找到檔案。它也不是相對載入的,因此它會正確處理符號連結,而之前您可能必須在 webpack 中硬式編碼路徑。
查看 babel.config.js
文件以取得更多資訊:專案範圍設定檔
此檔案與新的 overrides
屬性和 env
結合使用,讓您擁有單一設定檔,可適用於專案中的所有檔案,而非每個資料夾使用多個設定檔。
我們預設會排除 node_modules
,而且只會在根目錄中尋找,除非您選擇設定 .babelrcRoots
選項的陣列,例如 "babelrcRoots": [".", "node_modules/pkgA"]
宣告 Babel 版本 #7450
外掛可以檢查是否已載入特定版本的 Babel。此 API 將公開一個 assertVersion
方法,您可以在其中傳入 semver。
宣告輔助函式用於維持與 v6 的向下相容性。
import { declare } from "@babel/helper-plugin-utils";
export default declare(api => {
api.assertVersion(7);
// ...
});
Babel 外掛/預設值
它目前將 babel
物件、外掛/預設值選項和 dirname
視為第一個參數
module.exports = function(api, options, dirname) {};
babel-parser
(稱為 Babylon)
移除
*
外掛選項 #301
這最初新增於 v6.14.1(2016 年 11 月 17 日),因此不太可能有人使用此功能。
已移除此萬用選項;您應明確決定要啟用的外掛程式。
我們認為這對工具來說是個好主意,這樣它們就不必持續更新其設定檔,但也表示我們無法輕易進行重大變更。
之前
babelParser.parse(code, {
plugins: ["*"],
});
您可以使用下列方式取得舊有行為
babelParser.parse(code, {
plugins: [
"asyncGenerators",
"classProperties",
"decorators",
"doExpressions",
"dynamicImport",
"exportExtensions",
"flow",
"functionBind",
"functionSent",
"jsx",
"objectRestSpread",
],
});
請參閱 Babylon 的外掛程式選項。
將
decorators
外掛程式重新命名為decorators-legacy
已重新命名,以符合@babel/plugin-proposal-decorators
的legacy
選項。已實作新的decorators
外掛程式,實作新的裝飾器提案。
這兩個版本提案的語法不同,因此強烈建議使用decorators-legacy
,直到 Babel 實作新的語意。
已移除
classConstructorCall
外掛程式 #291
@babel/traverse
移除對 flow 繫結的支援 babel/babel#6528
此變更背後的原因是declare var foo
不會引入新的區域繫結,但它代表一個全域繫結。
getFunctionParent
不再會傳回Program
,請改用getProgramParent
#5923.
名為getFunctionParent
的函式傳回 Program 沒有意義,因此已移除。
若要取得等效行為,您需要進行類似變更
- path.scope.getFunctionParent()
+ path.scope.getFunctionParent() || path.scope.getProgramParent()
路徑替換/移除 API 現在會傳回新的路徑陣列
例如,使用 Path#insertBefore
或 Path#replaceWith
現在會永遠傳回新插入/替換路徑的陣列。
const node = t.nullLiteral();
const [replaced] = path.replaceWith(node);
replace.node === node; // => true
這在將數個節點插入較高層級範圍時特別有用,因為您可以立即在節點的新 Path
上呼叫 Path
API。
const parent = path.findParent(() => /* some selection criteria */);
const helperPaths = path.unshiftContainer("body", helpers);
// helperPaths can now be referenced, manipulated, etc.
AST 變更
新增 InterpreterDirective
節點 #7928
Babylon 已剖析「shebangs」(#!env node
),但會在 Program
節點中放入註解。現在我們只會為其建立實際節點。
新增新的 interpreter
欄位至 Program
節點。
extend interface Program {
interpreter: InterpreterDirective;
}
新增 InterpreterDirective
節點
interface InterpreterDirective <: Node {
type: "InterpreterDirective";
value: string;
}
JSX* 和 TS* 節點建構器 (來自 @babel/types 套件) 已重新命名
大小寫已變更:jsx
和 ts
現在是小寫。
- t.jSXIdentifier()
+ t.jsxIdentifier()
一般來說,我們已針對 Flow 的 TypeAnnotation
和 TypeScript 的 TSTypeAnnotation
區分節點類型,因此對於共用類型節點,TypeScript 會有 TS
前綴。
已移除 ArrowFunctionExpression
的 .expression
欄位
已移除 expression
欄位,以消除兩個不同的真實來源,並讓外掛程式不再需要手動將它們保持同步。現在您可以簡單地檢查函式主體是否為 BlockStatement
return {
visitor: {
ArrowFunctionExpression({ node }) {
- if (node.expression) {
+ if (node.body.type !== "BlockStatement") {
// () => foo;
}
}
}
};
已移除的 Token
在先前的版本中,tokens
始終附加至頂層的 AST。在最新版本的 @babel/parser
中,我們已移除此行為,並將其預設為停用,以提升解析器的效能。babel 中的所有用法均已移除,且 @babel/generator
不再使用 token 進行美化列印。
如果你的 babel 外掛目前使用 tokens
,請評估是否仍有必要,並盡可能嘗試移除用法。如果你的外掛真的仰賴取得 token,你可以重新啟用它,但請僅在別無他法時考慮這麼做,因為這會影響使用者的效能。
若要啟用,你需要將 babylon 的 tokens
選項設為 true。你可以直接從你的外掛執行此動作。
export default function() {
return {
manipulateOptions(opts, parserOpts) {
parserOpts.tokens = true;
},
...
};
}
已重新命名
下列節點已重新命名
6.x 名稱 | 7.x 名稱 | 範例 | PR |
---|---|---|---|
ExistentialTypeParam | ExistsTypeAnnotation | type A = B<*>; | #322 |
NumericLiteralTypeAnnotation | NumberLiteralTypeAnnotation | type T = 0; | #332 |
除了 AST 節點之外,@babel/types
中所有對應的函式也已重新命名。
import * as t from "@babel/types";
return {
- ExistentialTypeParam(path) {
- const parent = path.findParent((path) => path.isExistentialTypeParam());
- t.isExistentialTypeParam(parent);
+ ExistsTypeAnnotation(path) {
+ const parent = path.findParent((path) => path.isExistsTypeAnnotation());
+ t.isExistsTypeAnnotation(parent);
- return t.existentialTypeParam();
+ return t.existsTypeAnnotation();
},
- NumericLiteralTypeAnnotation(path) {
- const parent = path.findParent((path) => path.isNumericLiteralTypeAnnotation());
- t.isNumericLiteralTypeAnnotation(parent);
+ NumberLiteralTypeAnnotation(path) {
+ const parent = path.findParent((path) => path.isNumberLiteralTypeAnnotation());
+ t.isNumberLiteralTypeAnnotation(parent);
- return t.numericLiteralTypeAnnotation();
+ return t.numberLiteralTypeAnnotation();
}
};
已取代
在下列 AST 節點中,variance
欄位的數值已從單純的字串值變更為稱為 Variance
的 AST 節點本身。 #333
當在 babylon 中啟用 flow
外掛時,此欄位才可用。
- ObjectProperty
- ObjectMethod
- AssignmentProperty
- ClassMethod
- ClassProperty
- Property
新的 Variance
節點類型看起來像這樣
type VarianceNode = {
type: "Variance",
kind: "plus" | "minus",
};
return {
Property({ node }) {
- if (node.variance === "plus") {
+ if (node.variance.kind === "plus") {
...
- } else if (node.variance === "minus") {
+ } else if (node.variance.kind === "minus") {
...
}
}
};
位置變更
ObjectTypeIndexer
的位置資訊已變更,不包含分號。此變更與 flow-parser 保持一致,並具有相同的位置資訊。 #228
範例
var a: { [a: number]: string };
{
"type": "ObjectTypeIndexer",
"start": 9,
- "end": 29,
+ "end": 28,
"loc": {
"start": {
"line": 1,
"column": 9,
},
"end": {
"line": 1,
- "column": 29
+ "column": 28
}
}
}
移除
ForAwaitStatement
AST 節點 ForAwaitStatement
已移除,並以 ForOfStatement
節點中的 await
欄位取代 #349
interface ForOfStatement <: ForInStatement {
type: "ForOfStatement";
+ await: boolean;
}
return {
- ForAwaitStatement(path) {
- ...
+ ForOfStatement(path) {
+ if (path.node.await) {
+ ...
+ }
}
};
RestProperty & SpreadProperty
兩個 AST 節點 RestProperty
和 SpreadProperty
已移除,改為重複使用 RestElement
和 SpreadElement
#384
return {
SpreadElement(path) {
- ...
- },
- SpreadProperty(path) {
- ...
+ if (path.parentPath.isObjectExpression()) {
+ ...
+ } else if (path.parentPath.isArrayExpression()) {
+ ...
+ }
},
RestElement(path) {
- ...
- },
- RestProperty(path) {
- ...
+ if (path.parentPath.isObjectPattern()) {
+ ...
+ } else if (path.parentPath.isArrayPattern()) {
+ ...
+ }
}
};
請參閱我們的 Babel 升級 PR 和 Babylon AST 規格,以取得更多資訊。