[译]babel版本7.7.0功能更新

[译]babel版本7.7.0功能更新

7.7.0发布:错误恢复和TypeScript 3.7

2019年11月5日

今天我们将发布Babel 7.7.0!

此版本包括新的分析器功能,如顶级的await( await x(),第3阶段)和Flow enum声明(Flow的建议)。现在,@babel/parser可以选择从某些语法错误中恢复!

我们还增加了对TypeScript 3.7的支持:Babel可以解析和转换带有类型注释的私有类字段,使用declare关键字定义的公共类字段注释,类型声明函数签名和enum声明中的模板文字。

babel现在接受了三个新的配置文件:babel.config.json,babel.config.cjs和.babelrc.cjs,它们的行为和babel.config.js和.babelrc.js文件一样。

最后,Babel 7.7.0使用的内存比7.6.0少20%。

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


顶级await解析(#10449

顶级await proposal允许您在模块中await promise,就像它们被包装在一个大型异步函数中一样。例如,这对于有条件地加载依赖项或执行应用程序初始化很有用:

// Dynamic dependency path
const strings = await import(`./i18n/${navigator.language}.mjs`);

// Resource initialization
const connection = await dbConnector();

@babel/parser自版本7.0.0起,已支持await通过该allowAwaitOutsideFunction选项使用异步功能之外的功能。

版本7.7.0引入了一个新的topLevelAwait解析器插件,该插件有一些主要区别:

  • 根据await提案的要求,它仅允许顶层内部模块,而不允许内部脚本。这是必需的,因为基于同步脚本的模块系统(例如CommonJS)无法支持异步依赖关系。
  • 使用它可以检测正确的sourceType时间sourceType: "unambiguous"。请注意,由于await在脚本中是有效的标识符,因此许多看起来似乎毫不含糊的构造实际上是模棱两可的,Babel会将它们解析为脚本。例如,await -1可以是一个waiting表达式的waiting -1,或者是await和之间的差异1

如果@babel/parser直接使用,则可以启用topLevelAwait插件:

parser.parse(inputCode, {
  plugins: ["topLevelAwait"]
});

我们还创建了@babel/plugin-syntax-top-level-await软件包,您可以将其添加到Babel配置中:

// babel.config.js

module.exports = {
  plugins: [
    "@babel/plugin-syntax-top-level-await"
  ]
}

请注意,顶层使用await假定为模块捆绑程序中的支持。Babel本身并没有进行转换:如果您使用汇总,则可以启用该experimentalTopLevelAwait选项,而webpack 5支持该experiments.topLevelAwait选项。

从此版本开始,如果支持,它将自动启用@babel/preset-env。

解析器错误恢复(#10363

像许多其他JavaScript解析器一样,@babel/parser每当遇到某些无效语法时,都会引发错误。这种行为对于Babel来说效果很好,因为要将JavaScript程序转换为另一个程序,我们必须首先确保输入有效。

鉴于Babel的流行,还有许多其他工具依赖@babel/parser:首先是babel-eslint 和 Prettier。对于这两种工具,在出现第一个错误时无法使用时都不理想。

考虑以下代码,由于重复proto属性,该代码无效:

let a = {
  __proto__: x,
  __proto__: y
}

let a = 2;

ESLint和Prettier当前的工作流程如下:

  1. Prettier无法格式化文件
  2. ESLint报告Redefinition of __proto__ property解析器错误
  3. 您删除第二个__proto__属性
  4. Prettier无法格式化文件
  5. ESLint报告Identifier 'a' has already been declared错误
  6. 您删除第二个let关键字
  7. Prettier 格式化文件格式

如果它更像这样会更好吗?

  1. Prettier格式化文件格式
  2. ESLint报告两个错误:Redefinition of __proto__ propertyIdentifier 'a' has already been declared
  3. 您删除第二个__proto__属性和第二个let关键字

在这个版本中,我们添加一个新的选项@babel/parser:errorRecovery。设置为true时,生成的AST将具有一个errors属性,其中包含所有@babel/parser能够从以下其中恢复的错误:

const input = `
let a = {
  __proto__: x,
  __proto__: y
}
  
let a = 2;
`;

parser.parse(input); // Throws "Redefinition of __proto__ property"

const ast = parser.parse(input, { errorRecovery: true });
ast.errors == [
  SyntaxError: "Redefinition of __proto__ property",
  SyntaxError: "Identifier 'a' has already been declared",
];

@babel/parser仍然可以抛出,因为并非每个错误当前都可以恢复。我们将继续改善这些情况!

新的配置文件扩展名(#10501#10599

Babel 6仅支持一个配置文件:.babelrc,其内容必须使用JSON指定。

Babel 7更改了.babelrcs 的含义,并引入了两个新的配置文件:babel.config.js和.babelrc.js(您可以在docs中了解它们之间的区别)。我们使用JavaScript添加了配置文件,以允许在启用/禁用插件/选项时定义自己的逻辑。

但是,JSON文件的一大好处是更易于缓存。两次调用时,同一个JavaScript文件可以产生不同的值,而JSON文件可以保证始终对同一对象求值。此外,JSON配置易于序列化,而无法使用隐式数据或关系序列化JavaScript值(如函数或JavaScript对象)。

请注意,Babel在使用基于JavaScript的配置时也会缓存转换,但是必须评估config文件(以便知道缓存是否仍然有效),并手动配置缓存。

由于这些原因,Babel 7.7.0引入了对新配置文件的支持:babel.config.json,其行为与相同babel.config.js。

我们还添加了对两个不同配置文件的支持:babel.config.cjs和.babelrc.cjs,在中使用node的"type": "module"选项时必须使用package.json(因为Babel在配置文件中不支持ECMAScript模块)。除了这种"type": "module"差异之外,它们的行为与babel.config.js和完全相同.babelrc.js。

TypeScript 3.7(#10543#10545

TypeScript 3.7 RC支持可选的链接,无效的合并运算符,断言函数,类型字段声明以及许多其他与类型相关的功能。

自7.0.0起,通过和都支持Babel中的可选链(a?.b)和无效合并(a ?? b)。@babel/plugin-proposal-optional-chaining和@babel/plugin-proposal-nullish-coalescing-operator

在Babel 7.7.0中,您现在可以在断言函数和declare类字段中使用:

function assertString(x): assert x is string {
  if (typeof x !== "string") throw new Error("It must be a string!");
}

class Developer extends Person {
  declare usingBabel: boolean;
}

为了避免重大更改,我们推出了支持declare在一个标志背后类字段:"allowDeclareFields",双方支持@babel/plugin-transform-typescript和@babel/preset-typescript。这可能会成为默认行为,因此建议您迁移配置以使用它:

{
  "presets": [
    ["@babel/preset-typescript", {
      "allowDeclareFields": true
    }]
  ]
}

使用对象在已编译的JSX中传播(#10572

在JSX元素中使用传播属性时,Babel默认情况下会注入运行时帮助程序:

<a x {...y} />

// 

function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }

React.createElement("a", _extends({
  x: true
}, y));

2016年,随着对本地ES6的支持得到改善,我们添加了一个useBuiltIns选项,@babel/plugin-transform-react-jsx该选项允许编译后的输出直接使用Object.assign并删除多余的代码:

<a x {...y} />

// 

React.createElement("a", Object.assign({
  x: true
}, y));

但是,鉴于对对象传播的本地支持,它使我们能够生成更多优化的代码:

<a x {...y} />

//
React.createElement("a", { x: true, ...y });

您可以使用或启用该useSpread选项:@babel/preset-react@babel/plugin-transform-react-jsx

{
  presets: [
    ["@babel/react", { useSpread: true }]
  ]
}

内存使用率改进(#10480

从一开始,我们就一直在努力(#433#3475#7028等)来提高性能。Babel 7.7.0现在使用的内存减少了20%,与7.6.0相比,转换大型文件的速度提高了8%。

为了获得这些结果,我们优化了在生存期NodePath对象(用于包装每个AST节点)中完成的不同操作:

  1. 现在我们避免初始化一些很少使用的对象属性,直到需要它们为止,这使我们避免Object.create(null)为几乎每个AST节点分配资源。
  2. 通过用bookkeeping替换一些不常见的属性,从而@babel/traverse可以跳过更新它们,我们减少了每次访问单个节点的工作量。
  3. 我们通过将表示节点遍历(即,跳过,停止或删除)的状态的几个布尔属性压缩到位数组中来优化内存使用。

所有这些改进加起来在转换性能和内存使用方面存在以下差异:

您也可以检出上面图表的原始数据。如果您想了解更多有关此主题的信息,则可以阅读Jùnliàng关于他为获得这些改进所做的更改的详细文章

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,802评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,109评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,683评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,458评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,452评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,505评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,901评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,550评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,763评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,556评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,629评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,330评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,898评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,897评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,140评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,807评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,339评论 2 342

推荐阅读更多精彩内容