7.10.0 版本发布:preset-env 支持类字段、'#private in' 私有字段检查及更好的 React 摇树优化
本页面由 PageTurner AI 翻译(测试版)。未经项目官方认可。 发现错误? 报告问题 →
我们刚刚发布了 Babel 的新次版本更新!
本次 7.10 版本包含:
-
完整支持 Stage 1 新提案
#prop in obj私有字段检查功能 提案链接 -
@babel/preset-env现在可将 ES2015 风格的 Unicode 转义符 (\u{Babe1}) 编译为等效的传统语法 (\uDAAA\uDFE1) -
对可选链操作符 (
?.) 的两项优化 -
支持解析 Stage 1 新提案模块属性提案 (
import a from "./a.json" with type: "json") -
更好的 React 代码摇树优化支持 (如
React.memo)! -
设立 RFCs 仓库和 GitHub 讨论区!
您可在 GitHub 查看完整更新日志
伴随本次 Babel 发布,我们特别感谢 Nicolò 及社区杰出贡献者,推出了首个实验版本的新 polyfill 兼容架构(详见下文)!相关讨论始于一年前 Babel 仓库中的 RFC issue
另外,我们现已建立官方 RFC 流程,用于讨论对用户有重大影响的变更:请访问 babel/rfcs 仓库查看详情!同时,我们在仓库启用了 GitHub 讨论区,欢迎您提出反馈或疑问!
若您或公司希望支持 Babel 及 JavaScript 生态发展,可通过 Open Collective 进行捐赠,更可直接参与新 ECMAScript 提案的实现!作为志愿者驱动的项目,我们依赖社区支持来服务广大 JavaScript 用户。欢迎通过 team@babeljs.io 联系我们!
默认启用的新功能
支持解析 import.meta
在 Kiko 的贡献下,import.meta 解析功能现默认启用(该提案已进入 Stage 4)。请注意 @babel/preset-env 默认不支持其转换功能,因为该对象内容取决于具体引擎实现,未在 ECMAScript 规范中定义
console.log(import.meta); // { url: "file:///home/user/my-module.js" }
Transforming ​u{...}-style Unicode escapes (#11377)
我们还修复了长达五年的功能缺失:感谢 Justin,@babel/preset-env 现在默认支持编译 \u{...} 风格的 Unicode 转义符(适用于字符串和标识符)
var \u{1d49c} = "\u{Babe1}";
console.log(\u{1d49c});
var _ud835_udc9c = "\uDAAA\uDFE1";
console.log(_ud835_udc9c);
类属性与私有方法支持纳入 @babel/preset-env 的 shippedProposals 选项 (#11451)
最后,感谢 Jùnliàng 的贡献,我们已将 @babel/plugin-proposal-class-properties 和 @babel/plugin-proposal-private-methods 添加到 @babel/preset-env 的 shippedProposals 选项中。这些提案尚未进入 Stage 4(即还不是 ECMAScript 标准),但已在众多 JavaScript 引擎中默认启用。
如果您还不熟悉:
class Bork {
// Public Fields
instanceProperty = "bork";
static staticProperty = "babelIsCool";
// Private Fields
#xValue = 0;
a() {
this.#xValue++;
}
// Private methods
get #x() { return this.#xValue; }
set #x(value) {
this.#xValue = value;
}
#clicked() {
this.#x++;
}
}
若您错过了上个版本,在 7.9 中我们新增了选项:"bugfixes": true,该选项能显著减少代码输出量。
{
"presets": [
["@babel/preset-env", {
"targets": { "esmodules": true }, // Use the targets that you was already using
"bugfixes": true // will be default in Babel 8
}]
]
}
改进可选链 ?. 的使用体验 (#10961, #11248)
在 TypeScript 3.9 中,非空断言(后缀 !)与可选链的交互行为已更改,使其更具实用性。
foo?.bar!.baz
在 TypeScript 3.8 和 Babel 7.9 中,上述代码会被解析为 (foo?.bar)!.baz:"若 foo 非空值,则获取其 .bar 属性。随后信任 foo?.bar 永不为空并始终获取其 .bar 属性"。这意味着当 foo 为空值时,该代码将始终抛出错误,因为我们试图从 undefined 获取 .baz。
在 TypeScript 3.9 和 Babel 7.10 中,该代码行为类似于 foo?.bar.baz:"若 foo 非空值,则获取其 .bar.baz 属性,并相信我 foo?.bar 不为空值"。感谢 Bruno 协助实现此功能!
此外,类字段提案近期新增支持将可选链 ?. 与私有字段结合使用。这意味着以下代码现已合法:
obj?.property.#priv;
obj?.#priv;
注意在第二个示例中,若 obj 非空值但不包含 #priv 字段,仍会抛出错误(与 obj.#priv 的行为一致)。您可阅读下一节了解如何规避此问题!
私有字段的 in 运算符支持 (#11372)
class Person {
#name;
hug(other) {
if (#name in other) console.log(`${this.#name} 🤗 ${other.#name}`);
else console.log("It's not a person!")
}
}
此 Stage 1 提案允许您静态检查指定对象是否包含特定私有字段。
私有字段内置"品牌检查"机制:若尝试在未定义该字段的对象中访问它,将抛出异常。您可通过 try/catch 语句利用此行为判断对象是否包含特定私有字段,而本提案提供了更简洁且健壮的语法实现此功能。
你可以在提案描述中了解更多详情。要测试此提案,请安装 @babel/plugin-proposal-private-property-in-object 插件并添加到 Babel 配置中。感谢 Justin 的 PR 贡献!
模块属性解析器支持 (#10962)
模块属性提案(Stage 1 阶段)允许为引擎、模块加载器或打包器提供导入文件的附加信息。例如,可以显式指定文件应作为 JSON 解析:
import metadata from "./package.json" with type: "json";
该特性也可用于动态 import() 调用。注意支持尾随逗号的设计,这使添加/删除第二个参数更加便捷!
const metadata = await import(
"./package.json",
{ with: { type: "json" } },
);
感谢 Vivek 的贡献,Babel 现已支持解析这些属性:你可以在 Babel 配置中添加 @babel/plugin-syntax-module-attributes 插件;若直接使用 @babel/parser,则可启用 moduleAttributes 插件。目前我们仅接受 type 属性,未来可能根据提案演进放宽此限制。
Babel 不会_转换_这些属性,它们应由你的打包器或自定义插件处理。当前 Babel 的模块转换器会_忽略_这些属性。我们正在讨论未来是否应透传这些属性。
React 组件树摇动优化 (#11428)
React 提供了众多用于注解或包装元素的纯函数,例如 React.forwardRef、React.memo 或 React.lazy。但压缩工具和打包器无法识别这些函数的纯度,因此无法移除它们。
感谢 Parcel 团队的 Devon,@babel/preset-react 现在会在这些函数调用处注入 /*#__PURE__*/ 标注,标记它们可安全进行树摇动优化。此前我们仅对 JSX 本身应用此优化(例如 <a></a> 转为 /*#__PURE__*/React.createElement("a", null))。
import React from 'react';
const SomeComponent = React.lazy(() => import('./SomeComponent'));
import React from 'react';
const SomeComponent = /*#__PURE__*/React.lazy(() => import('./SomeComponent'));
实验性 polyfill 新架构 (#10008, babel-polyfills)
过去三年中,@babel/preset-env 通过仅转译目标环境需要的语法特性并注入 core-js polyfill,有效帮助用户缩减包体积。当前 Babel 提供三种不同的 core-js polyfill 注入方式:
-
使用
@babel/preset-env的useBuiltIns: "entry"选项,可为目标浏览器不原生支持的所有 ECMAScript 功能注入 polyfill; -
使用
useBuiltIns: "usage"选项时,Babel 仅对源代码中实际使用的、且目标环境不支持的 ECMAScript 特性注入 polyfill; -
使用
@babel/plugin-transform-runtime时,Babel 会为core-js支持的所有已用 ECMAScript 特性注入 "纯净" ponyfills(不会污染全局作用域),该方式通常被库作者采用。
我们在 JavaScript 生态中的独特位置,让我们能将这些优化推向更深层次。对部分用户而言,@babel/plugin-transform-runtime 相比 useBuiltIns 具备显著优势,但它未考虑目标环境:如今已是 2020 年,几乎没人需要加载 Array.prototype.forEach 的 polyfill。
此外,为何要将自动注入必要 polyfill 的能力局限在 core-js?还有 DOM polyfill、Intl polyfill 以及无数其他 Web 平台 API 的 polyfill。并非所有人都想使用 core-js;存在多种 ECMAScript polyfill 方案,它们各有取舍(例如源码体积与规范兼容性的权衡),用户理应有选择 polyfill 的自由。例如,我们正积极推进与 es-shims 的集成。
如果注入逻辑能与 polyfill 的实际可用性/需求数据解耦,使其可独立使用和开发,会如何?
我们现在发布四个新软件包的实验性初版:
这些包均支持通过 method 选项调整注入方式(类似于 @babel/preset-env 和 @babel/plugin-transform-runtime 现有功能)。您可将 polyfill 注入入口点(仅限全局作用域)或通过代码直接使用(支持全局作用域和"纯"模式)。下方自定义的 CodeSandbox 可让您体验不同 polyfill 选项的差异。
我们还发布了 @babel/helper-define-polyfill-provider:全新的辅助工具包,让 polyfill 作者和用户能定义_专属的_ polyfill 提供者插件。
特别感谢 Jordan 与 Nicolò 协作,使构建 es-shims 插件成为可能!
若需深入了解这些包并学习配置方法,请查阅项目的 README。
这些包仍处于实验阶段。欢迎在 Twitter 或 GitHub 提交反馈,但请勿用于生产环境。例如,部分 polyfill 仍需接入,且尚未在生产应用中测试插件稳定性。
