# 升级到 Babel 7

在升级到 Babel 7 时请用户参考此文档。在此处 (opens new window) 检查 API/集成更改。

因为并非每个重大变更都会影响每个项目,所以我们根据升级时变更中断测试的可能性对这些部分进行了排序。

# 所有的通天塔 (opens new window)

已删除对 Node.js 0.10、0.12、4 和 5 的支持#5025 (opens new window)#5041 (opens new window)#7755 (opens new window)#5186 (opens new window)

我们强烈建议您使用更新版本的 Node.js (LTS v8),因为以前的版本没有得到维护。有关详细信息,请参阅nodejs/LTS 。 (opens new window)

这只是意味着 Babel本身不会在旧版本的 Node 上运行。它仍然可以输出在旧 Node 版本上运行的代码。

# 配置查找更改 (opens new window)

有关详细信息,请阅读我们的6.x 与 7.x 比较 (opens new window)

node_modulesBabel 之前在处理、符号链接和 monorepos方面遇到过问题。我们做了一些更改来解决这个问题:Babel 将停止在边界处查找,package.json而不是在链上查找。对于 monorepos,我们添加了一个新babel.config.js文件,该文件将我们的配置集中在所有包中(或者,您可以为每个包创建一个配置)。在 7.1 中,我们引入了一个rootMode (opens new window) 选项,用于在必要时进行进一步查找。

# 年度预设 弃用

“env”预设已经推出一年多了,它完全取代了我们之前拥有和建议的一些预设。

  • babel-preset-es2015
  • babel-preset-es2016
  • babel-preset-es2017
  • babel-preset-latest
  • 以上的组合^

这些预设应替换为“env”预设。

# 舞台预设 弃用

我们正在删除阶段预设,以支持明确的提案使用。可以查看stage-0 README (opens new window) 了解更多迁移步骤。

要自动执行此操作,您可以运行(在此处 (opens new window) npx babel-upgrade 添加 PR )。

# @babel/polyfill 删除 提案 polyfills

基于类似的想法,我们已经从@babel/polyfill.

现在@babel/polyfill主要只是 v2 的别名core-js来源 (opens new window)

在它曾经只是 2 个进口之前:

JavaScript

import "core-js/shim"; // included < Stage 4 proposals
import "regenerator-runtime/runtime";

如果您想使用提案,则需要独立导入这些提案。core-js (opens new window) 您应该直接从包或 npm 上的另一个包导入它们。

例如

JavaScript

// for core-js v2:
import "core-js/fn/array/flat-map";

// for core-js v3:
import "core-js/features/array/flat-map";

以下是 v2 中 Stage < 3 提案 polyfill 的列表core-js

细节JavaScript


# 版本控制/ 依赖关系

大多数插件/顶级包现在都有一个peerDependencyon @babel/core

# 包重命名 (opens new window)

  • babylon就是现在@babel/parser

您仍然可以在配置中使用包名称的简写版本(删除 or preset-) ,但为了清楚起见,我选择使用整个包名称(也许我们应该删除它,因为它不会节省那么多输入plugin-反正)。

{
-  "presets": ["@babel/preset-react"],
+  "presets": ["@babel/react"], // this is equivalent
-  "plugins": ["@babel/transform-runtime"],
+  "plugins": ["@babel/plugin-transform-runtime"], // same
}

# 范围 (opens new window)

最重要的变化是最终将所有包切换到作用域包( (opens new window) monorepo 中的文件夹名称未更改,但其中的名称package.json是)。

这意味着不会再有意外/故意域名抢注的问题,与社区插件的明确分离以及更简单的命名约定。

您的依赖项需要像这样修改:

babel-cli-> @babel/cli。对于我们来说,我们基本上是从替换babel-@babel/.

#配置 (opens new window)

您仍然可以使用指定预设或插件的简写方式。然而,由于切换到范围包,您仍然必须指定,@babel/就像您有自己的预设要添加到配置中一样。

babel.config.js

module.exports = {
  presets: ["@babel/env"], // "@babel/preset-env"
  plugins: ["@babel/transform-arrow-functions"], // same as "@babel/plugin-transform-arrow-functions"
};

# 切换到-proposal-TC39 提案

这意味着任何不在年度版本中的插件(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-or ,但这些都是不必要的。-es2015-

@babel/plugin-transform-es2015-classes成了@babel/plugin-transform-classes

# "use strict"``thisCommonJS (opens new window)

Babel 6 对 ES6 模块的转换不加区别地运行在它被告知要处理的任何文件上,从不考虑文件中是否真的有 ES6 导入/导出。this这具有将文件范围的引用重写为beundefined并插入"use strict"到由 Babel 处理的所有 CommonJS 模块顶部的效果。

JavaScript

// input.js
this;

JavaScript

// output.js v6
"use strict"; // assumed strict modules
undefined; // changed this to undefined

JavaScript

// output.js v7
this;

此行为在 Babel 7 中受到限制,因此对于transform-es2015-modules-commonjs转换,只有在文件中包含 ES6 导入或导出时才会更改文件。(编者注:如果我们登陆https://github.com/babel/babel/issues/6242 (opens new window) ,这可能会再次发生变化,因此我们希望在发布之前重新审视它)。

JavaScript

// input2.js
import "a";

JavaScript

// output.js v6 and v7
"use strict";
require("a");

如果您依赖 Babel"use strict"自动注入所有 CommonJS 模块,您将需要transform-strict-mode在 Babel 配置中显式使用该插件。

# React 和 Flow预设

babel-preset-react一直包含流插件。这导致了很多用户的问题,他们flow由于拼写错误而无意中使用了语法,或者在没有对其flow自身进行类型检查的情况下添加它,从而导致错误。

当我们决定支持 TypeScript 时,这个问题变得更加复杂。如果您想使用 React 和 TypeScript 预设,我们必须想出一种方法来通过文件类型或指令自动打开/关闭语法。最后,更容易将预设完全分开。

Presets 使 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
}

# 选项解析 (opens new window)

Babel 的配置选项比 Babel 6 中的更严格。在逗号分隔的预设列表中,例如,"presets": 'es2015, es2016'以前在技术上可行,现在它会失败,需要更改为数组#5463 (opens new window)

请注意,这不适用于 CLI,它--presets es2015,es2016肯定仍然有效。

{
-  "presets": "@babel/preset-env, @babel/preset-react"
+  "presets": ["@babel/preset-env", "@babel/preset-react"]
}

# 插件/预设导出 (opens new window)

所有插件/预设现在应该导出一个函数而不是一个对象以保持一致性(通过 babel/babel#6494 (opens new window) )。这将帮助我们进行缓存。

# 解析基于字符串的配置 (opens new window)

在 Babel 6 中,直接传递给 Babel 的值(不是从配置文件)是相对于正在编译的文件进行解析的,这导致了很多混乱。

在 Babel 7 中,值是相对于加载它们的配置文件或相对于工作目录一致地解析的。

对于presetsplugins值,此更改意味着 CLI 在以下情况下将表现良好

babel --presets @babel/preset-env ../file.js

假设您的node_modules文件夹位于.,在 Babel 6 中,这将失败,因为找不到预设。

此更改也会影响only并将ignore在接下来进行扩展。

# 基于路径only模式 (opens new window) ignore

在 Babel 6 中,onlyignore被视为通用匹配字符串,而不是文件路径 glob。这意味着例如*.foo.js会匹配./**/*.foo.js,这让大多数用户感到困惑和惊讶。

在 Babel 7 中,这些现在被视为基于路径的 glob 模式,可以是相对路径或绝对路径。这意味着,如果您正在使用这些模式,您现在可能至少需要**/为它们添加一个前缀,以确保您的模式与目录深度匹配。

onlyignore模式仍然适用于目录,因此您也可以only: './tests'仅用于编译目录中的文件tests,而无需用于**/*.js匹配所有嵌套文件。

# Babel 的 CLI命令

该命令--copy-files的参数babel告诉 Babel 复制 Babel 不知道如何处理的目录中的所有文件,现在也将复制未通过 /only检查的文件ignore,而之前它会默默地跳过所有忽略的文件。

# @babel/node (opens new window)

Babel 6 中的命令babel-node是包的一部分babel-cli。在 Babel 7 中,这个命令已经被拆分到它自己的@babel/node包中,所以如果你正在使用那个命令,你会想要添加这个新的依赖项。

# @babel/runtime, @babel/plugin-transform-runtime (opens new window)

我们已经将 Babel 的助手从它在运行时的“polyfilling”行为中分离出来。公关 (opens new window) 中的更多细节。

@babel/runtime 现在只包含助手,如果你需要,core-js你可以使用@babel/runtime-corejs2 (opens new window) 和转换中提供的选项。对于两者,您仍然需要@babel/plugin-transform-runtime (opens new window)

# 只有帮手 (opens new window)
# install the runtime as a dependency
npm install @babel/runtime
# install the plugin as a devDependency
npm install @babel/plugin-transform-runtime --save-dev

babel.config.json

{
  "plugins": ["@babel/plugin-transform-runtime"]
}

# Helpers + polyfillingcore-js来自 (opens new window)

因此,如果您需要 的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,
+   }],
  ]
}

# 规范合规性 (opens new window)

# @babel/plugin-proposal-object-rest-spread (opens new window)

对象中的 RestElement 后不能有尾随逗号#290 (opens new window) 中等的

var {
-  ...y, // trailing comma is a SyntaxError
+  ...y
} = { a: 1 };

由于 Object Spread 定义了新属性并Object.assign只是设置了它们,Babel 已经更改了默认行为以更符合规范。

  • objectSpread 辅助函数
  • 扩展辅助函数

JavaScript

// input
z = { x, ...y };

JavaScript

// v7 default behavior: ["proposal-object-rest-spread"]
function _objectSpread(target) { ... }

z = _objectSpread({
  x
}, y);

JavaScript

// Old v6 behavior: ["proposal-object-rest-spread", { "loose": true }]
function _extends(target) { ... }

z = _extends({
  x
}, y);

JavaScript

// Substitute for Object.assign: ["proposal-object-rest-spread", { "loose": true, "useBuiltIns": true }]
z = Object.assign(
  {
    x,
  },
  y
);

# @babel/plugin-proposal-class-properties (opens new window)

默认行为默认更改为以前的“规范”

JavaScript

// input
class Bork {
  static a = "foo";
  y;
}

JavaScript

// 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",
});

JavaScript

// 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成两个重命名的提案 (opens new window)

这是一个很长的时间,但终于改变了。

@babel/plugin-proposal-export-default-from

JavaScript

export v from "mod";

@babel/plugin-proposal-export-namespace-from

JavaScript

export * as ns from "mod";

# @babel/plugin-transform-template-literals (opens new window)

模板文字修订已更新#5523 (opens new window) 低的

请参阅Template Literals Revision 提案。

它导致 Babel 6 抛出Bad character escape sequence (5:6).

JavaScript

tag`\unicode and \u{55}`;

这已在 Babel 7 中修复并生成如下内容:

JavaScript

// 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);

JavaScript

// loose mode
function _taggedTemplateLiteralLoose(strings, raw) {
  strings.raw = raw;
  return strings;
}
var _templateObject = /*#__PURE__*/ _taggedTemplateLiteralLoose(
  [void 0],
  ["\\unicode and \\u{55}"]
);
tag(_templateObject);

常规模板文字默认为以前的“规范”模式

JavaScript

// input
`foo${bar}`;

JavaScript

// default v7 behavior: ["@babel/plugin-transform-template-literals"]
"foo".concat(bar);

JavaScript

// old v6 behavior: ["@babel/plugin-transform-template-literals", { "loose": true }]
"foo" + bar;

# @babel/plugin-proposal-decorators (opens new window)

期待新的装饰器提案实施,我们决定将其设为新的默认行为。这意味着要继续使用当前的装饰器语法/行为,您必须将选项设置legacytrue.

 {
   "plugins": [
-    "@babel/plugin-proposal-decorators"
+    ["@babel/plugin-proposal-decorators", { "legacy": true }]
   ]
 }

注意:如果您正在使用包含此插件的@babel/preset-stage-0or @babel/preset-stage-1,则必须将decoratorsLegacy选项传递给他们。

# @babel/plugin-proposal-pipeline-operator (opens new window)

默认情况下,较新的不断变化的提案会出错,并且会要求每个人都选择加入特定的提案,而事情仍然<阶段 2。这在这篇文章中有更多解释 (opens new window)

{
  "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 (opens new window) 低的

TC39 决定放弃这个提案。您可以将逻辑移动到构造函数或静态方法中。

有关详细信息,请参阅/docs/plugins/transform-class-constructor-call/ 。 (opens new window)

  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 (opens new window)

我们babel-plugin-transform-async-to-module-method通过将其作为一个选项合并到常规异步插件中。

{
  "plugins": [
-    ["@babel/transform-async-to-module-method"]
+    ["@babel/transform-async-to-generator", {
+      "module": "bluebird",
+      "method": "coroutine"
+    }]
  ]
}

# babel (opens new window)

丢包# (opens new window) babel5293低的

此软件包当前会向您提供一条错误消息,让您babel-cli改为在 v6 中安装。我认为我们可以用这个名字做一些有趣的事情。

# @babel/register (opens new window)

babel-core/register.js已被删除#5132 (opens new window) 低的

babel-core/register在 Babel 7 中删除了不推荐使用的用法;而是使用独立包@babel/register

作为新的依赖项安装@babel/register

  • npm
npm install --save-dev @babel/register
  • yarn
yarn add --dev @babel/register

使用摩卡升级:

- mocha --require babel-core/register
+ mocha --require @babel/register

@babel/register现在也只会直接编译当前工作中的文件(已完成以修复符号链接问题)。

@babel/register选项现在被替换而不是合并

# @babel/generator (opens new window)

删除quotes选项#5154 (opens new window) ]没有任何

如果你想为编译后的输出格式化,你可以使用 recast/prettier/escodegen/fork babel-generator。

此选项仅在 v6.18.0 之前显式可用babel-generator,当时我们公开了parserOptsand generatorOpts。因为那个版本中有一个错误,所以没有人应该在 Babel 本身中使用这个选项。

删除flowUsesCommas选项#5123 (opens new window) 没有任何

目前,流对象类型中有 2 种受支持的语法(,和)。;

此更改只是使 babel-generator 输出,而不是;.

# @babel/core (opens new window)

删除babel-core/src/api/browser.js#5124 (opens new window) 没有任何

babel-browser已在 6.0 中删除。如果你需要在浏览器或非 Node 环境中使用 Babel,请使用@babel/standalone (opens new window)

Babel 将filename作为绝对路径返回#8044 (opens new window)

# @babel/preset-env (opens new window)

loose模式现在将自动排除typeof-symbol转换(许多使用松散模式的项目都在这样做)。

Last Updated: 6/14/2023, 8:56:23 AM