7.8.0版发布——ECMAScript 2020,.mjs配置文件和@babel/cli的改进

334 阅读3分钟

7.8.0版发布——ECMAScript 2020、.mjs配置文件和@babel/cli改进

这是今年的第一个版本!🎉

Babel 7.8.0默认支持ECMAScript 2020的新特性:你不需要再为nullish coalescing (??)、optional chaining (?.)和动态import() 的预设-env启用个别插件了。

我们还完成了将不同的配置文件与Node.js原生支持的格式相统一的工作,这个过程我们在7.7.0版本中就开始了。

最后,Babel的CLI现在支持两个新选项:--out-file-extension--copy-ignored

你可以在GitHub上阅读整个更新日志。


Abdul AliJack IsherwoodJayen AsharJames BeaversKlaus MeinhardtOleksandr FediashovSiddhant N TrivediTsubasa NakayamaYordis PrietoZYSzys的第一个PR表示感谢!

我们也要感谢Thomas Smith自愿帮助我们维护重要的 babel-sublime语法高亮插件,并欢迎Raja Sekar,我们的Babel组织的新成员!

如果你或你的公司想支持Babel和JavaScript的发展,但不确定如何支持,你可以在我们的开放集体中为我们捐款,更好的是,直接与我们合作实施新的ECMAScript提案作为一个志愿者驱动的项目,我们依靠社区的支持来资助我们支持广大的JavaScript用户。如果你想讨论更多,请联系team@babeljs.io!

我们最近发表了一篇资助帖子,详细介绍了我们的资助计划和目标。请看!

ECMAScript 2020默认支持

在上次会议中,TC39将nullish凝聚和可选链的提案移到了第四阶段!

当一个表达式评估为nullundefined 时,nullish凝聚运算符允许你提供一个后退值。

const name = person.fullName ?? "Anonymous";
console.log(`Hello, ${name}!`);

这类似于逻辑OR (||) 操作符的工作方式。不同的是,虽然|| 检查 "falsy "值(即undefined,null,false,0,0n"" ),但?? 只检查 "nullish "值。这更符合 "未提供的值 "的心理模型,并且对可能是虚假的、但有效的值更有效。

const element = { index: 0, value: "foo" };

const index = element.index ?? -1; //  0 :D
const index = element.index || -1; // -1 :(

可选链建议使用相同的 "空值 "概念,允许对可能为空的值进行可选的属性访问。它还支持可选的函数调用和计算的属性。

const city = person.address?.city; // person.address could be not defined
const isNeighbor = person.address?.isCloseTo(me);

person.sayHayUsing?.("Twitter"); // The person.sayHayUsing method could be not defined 

现在你可以在你的代码中安全地使用这些新特性了如果你已经在使用@babel/preset-env ,你可以使用这两个操作符,它们将根据你的目标进行编译,就像其他ECMAScript特性一样。如果你以前直接使用@babel/plugin-proposal-nullish-coalescing-operator@babel/plugin-proposal-optional-chaining ,你可以从你的配置中删除它们。

{
  "presets": [
    ["@babel/env", { "targets": ["last 2 versions"] }]
  ],
  "plugins": [
-   "@babel/proposal-optional-chaining",
-   "@babel/proposal-nullish-coalescing-operator"
  ] 
}

这些功能现在在@babel/parser 中也是默认启用的:如果你以前直接使用它,你可以删除nullishCoalescingOperatoroptionalChaining 的分析器插件。我们还启用了动态import() (从v7.5.0开始已经包含在@babel/preset-env )的解析功能,所以你可以安全地删除dynamicImport 插件。

支持每个配置文件的扩展名

Babel 6支持单一的、基于JSON的配置文件:.babelrc

在Babel 7.0.0中,我们引入了babel.config.js (它有不同的解析逻辑)和.babelrc.js 。对于需要更高的灵活性的场景,JavaScript 配置文件是非常有用的。当时的情况就是这样。

Node.js文件类型babel.config.__.babelrc.__
.js✔️支持✔️支持
.json❌ 不支持❔ 支持,有隐式扩展

ℹ️我们强烈建议阅读关于babel.config.js.babelrc.js 之间的差异!

最近,Node.js 13.2.0发布了,增加了对本地ECMAScript模块和.cjs.mjs 文件扩展的支持。在Babel 7.7.0中,我们增加了对.cjs 配置文件的支持,允许用户在不破坏Babel的情况下在他们的package.json 中启用"type": "module" ,同时也支持babel.config.json ,这允许在整个项目中进行静态配置。

Node.js文件类型.babel.config.__.babelrc.__
.js✔️ 未启用"type": "module" 时支持。✔️ 未启用"type": "module" 时支持。
.json✔️支持❔ 支持,有隐式扩展
.cjs✔️ 已支持✔️支持
.mjs不支持不支持

此版本使Babel与Node.js原生支持的文件类型一致,允许.babelrc.json,babel.config.mjs, 和.babelrc.mjs

Node.js文件类型.babel.config.__.babelrc.__
.js✔️支持✔️支持
.json✔️支持✔️支持
.cjs✔️支持✔️支持
.mjs✔️支持✔️支持

请记住,ECMAScript模块是异步的:这就是为什么,例如,你不能require() ,而必须使用import() ,它返回一个承诺。

由于这些原因,它们只能在通过基于承诺或基于回调的入口点调用Babel时使用。它们已经可以在@babel/clibabel-loadergulp-babel ,并且它们将在下一个版本的rollup-plugin-babel 。请注意,它们还不被babel-eslint 所支持。

新的CLI选项

我们为@babel/cli 添加了两个新的标志:--copy-ignored--out-file-extension

--copy-ignored 可以用来复制那些不被Babel转译的文件,因为它们被 CLI选项忽略了,或者因为 在配置文件中被设置了。--ignore "ignore"

⚠️ 为了保持向后兼容,在Babel 7.8.4中,--copy-ignored 选项的默认值已改为true 。如果您想禁用它,可以使用--no-copy-ignored

这与--copy-files 选项的工作原理类似,但--copy-files 是为了复制任何因为不是JavaScript文件而没有转码的文件(例如:.css.json ),而不是明确忽略的文件。

--out-file-extension 可以用来配置Babel生成的文件的扩展名。例如,如果您在Node.js中转译包含本地ECMAScript模块的 文件,并希望生成CommonJS文件,您可能需要使用 扩展。.js .cjs

$ babel src --out-dir lib-cjs --out-file-extension cjs

为Babel 8做准备

在我们的总括问题中,我们开始着手准备Babel 8.0.0版本。#10746.

Babel 8将只包含突破性的变化:我们将在同一天发布一个次要版本,包含所有的错误修复和新功能,否则将在8.0.0中发布。

虽然我们预计不会有巨大的迁移路径,但有两个问题我们想提请您注意。

从preset-env中提取目标解析器和compat数据

各种第三方预设目前正在使用@babel/preset-env's内部逻辑来解析编译目标或检索有关必要的插件和polyfills的信息。

我们已经决定通过提供两个新的公共包来正式支持这两个用例。

  • @babel/helper-compilation-targetsBabel8是由一个名为 "Babel8 "的插件组成的,它导出了一个函数来规范化指定的目标和其他一些相关的实用程序。

    import getTargets from "@babel/helper-compilation-targets";
    
    getTargets({
      browsers: ["last 2 chrome versions"],
      node: 10
    }) == {
      chrome: "77.0.0",
      node: "10.0.0"
    }
    
  • @babel/compat-data,其中包含一个JSON文件的集合,我们在其中存储了每个插件或core-js@2 polyfill所需的所有浏览器版本。它主要是从 compat-table生成,但我们将来可能会添加其他数据源。如果你需要core-js@3 polyfills的数据,你可以使用 core-js-compat.

我们计划从Babel 8开始不允许使用内部文件。如果你依赖其他内部API,请让我们知道!

引入选择更严格的AST验证

@babel/types 已经执行了许多检查以确保你正在构建的AST是有效的。例如,这段代码会抛出,因为你不能用语句来代替表达式。

// foo = if (true) {}

t.assignmentExpression(
  "=",
  t.identifier("foo"),
  t.ifStatement(t.booleanLiteral(true), t.blockStatement([]))
);

我们正在引入更严格的验证,以防止更多无效的AST:不仅从树形的角度来看,而且还确保在正确位置的节点携带有效的信息。例如,从Babel 8开始,t.identifier("123") 将被禁止,因为123 不是一个有效的标识符。

我们不能在Babel 7.8.0中启用这些检查,因为破坏现有插件的风险太高了,但我们强烈鼓励您使用BABEL_TYPES_8_BREAKING=true 环境变量来启用这些更严格的检查,并公开问题(或者更好,PR!)来修复您正在使用的不能在Babel 8中工作的插件。