Skip to main content

Babel 路线图

本文档概述了我们的团队成员希望在今年进行的一些改进。

¥This document outlines some of the improvements our team members would like to work on during this year.

这远不是我们将为 Babel 带来的所有新功能或重要更改的完整列表,但如果你对项目的总体方向感兴趣,这是一个很好的总结。我们实际上可能不会完成所有列出的点,或者可能会将其中一些推迟到明年。其中一些有明确的起点和终点,而另一些则需要更多的研究或 RFCs

¥This is far from being a complete list of all the new features or important changes that we'll bring to Babel, but it's a good summary if you are interested in the general direction that the project is moving toward. We may not actually finish every listed point or may delay some of them to the next year. Some of them have clear starting and ending points, while others need more research or RFCs.

如果贵公司有兴趣并想直接赞助任何特定项目,请 伸手

¥If your company is interested and would like to directly sponsor any particular item please reach out!

Babel 2021 路线图

¥Babel 2021 Roadmap

Babel 8

我们谈论 Babel 8 版本已经有一年多了(我们最初是在一年前安排的)!然而,我们现在比以往任何时候都更接近它的发布!

¥We have been talking about the Babel 8 release for more than one year (we initially scheduled it about one year ago)! However, we are now closer then ever to its release!

剩下的大部分任务都在 跟踪问题 中,但还是有一些阻碍:

¥Most of the remaining tasks are in the tracking issue, but there are still a few blockers:

  • 我们希望放弃对 Node.js 10 的支持,该支持将于 2021-04-30 停止维护。

    ¥We want to drop support for Node.js 10, which stops being maintained on 2021-04-30.

  • 我们希望将 Babel 作为纯 ESM 包发布。我们现在正在将我们的源代码转换为与 Node.js 的 ESM 实现兼容,同时我们正在研究如何让当前使用 Babel 的人更容易将 ESM 编译为 CJS。

    ¥We would like to release Babel as a pure ESM package. We are now in the process of converting our sources to be compatible with Node.js' ESM implementation, and while doing so, we are examining how we can make it easier for people that currently use Babel to compile ESM to CJS.

  • 我们正在尝试使我们的 TypeScript AST 与 typescript-eslint 项目保持一致。我们的 AST 几乎相同,但我们需要引入一些小的突破性更改才能完全对齐。

    ¥We are trying to align our TypeScript AST with the typescript-eslint project. Our ASTs are almost identical, but we need to introduce some small breaking changes to fully align.

  • 我们的发布基础设施还不支持预发布,或者使用多个 "main" 分支(一个用于 Babel 8,一个用于 Babel 7)。

    ¥Our release infrastructure doesn't support yet pre-releases, or using multiple "main" branches (one for Babel 8 and one for Babel 7).

  • 我们还没有想出 Babel 7 维护的政策。

    ¥We haven't figured out yet a policy for Babel 7 maintenance.

实现新的 TC39 提案

¥Implement new TC39 proposals

Babel 目前可以解析所有 Stage 3 提案,我们可以转换所有这些提案,除了顶层 await、导入断言和 JSON 模块(最好由使用依赖图的打包程序处理)。

¥Babel can currently parse all the Stage 3 proposals, and we can transform all of them except for top-level await, import assertions and JSON modules (which are best handled by bundlers working with the dependencies graph).

我们支持所有第 2 阶段的提案,除了:

¥We support all the Stage 2 proposals except for:

  • 装饰器提案的新迭代(我们需要同时实现解析和转换);

    ¥The new iteration of the decorators proposal (we need to implement both parsing and transform);

  • 模块块提案的转换(我们在 Babel 7.13.0 中实现了解析)。

    ¥Transform for the Module Blocks proposal (we implemented parsing in Babel 7.13.0).

我们将实现对装饰器的支持,并研究是否以及如何实现模块块的转换。

¥We will implement support for decorators, and investigate if and how we can implement a transform for module blocks.

虽然我们不支持很多第 1 阶段的提案,但最近对管道运算符和执行表达式进行了更新。由于我们已经支持这些提案并且社区对它们感到非常兴奋,我们将更新我们的实现。

¥While we don't support many Stage 1 proposals, there have been recent updates to the pipeline operator and to do expressions. Since we already support those proposals and the community is quite excited about them, we will update our implementations.

还有其他一些建议(例如模式匹配)我们尚未实现,因为它们的拥护者希望对语法和语义进行重大更改。但是,我们正在密切关注它们的发展,一旦它们稳定一点,我们就会在 Babel 中实现它们。

¥There are also other proposals (such as pattern matching) that we have not yet implemented because their champions expect to do significant changes to the syntax and semantics. However, we are closely following their development, and will implement them in Babel as soon as they stabilize a bit.

@babel/preset-env 移动到 @babel/core

¥Move @babel/preset-env into @babel/core

一个最小的 Babel 转换设置至少需要三个包:

¥A minimal Babel transforming setup requires at least three packages:

  • @babel/core

  • @babel/preset-env

  • Babel "runner"(@babel/clibabel-loader@rollup/plugin-babel 等)

    ¥a Babel "runner" (@babel/cli, babel-loader, @rollup/plugin-babel, etc)

@babel/preset-env 直接移入 @babel/core 有两大优势:

¥Moving @babel/preset-env directly into @babel/core has two big advantages:

  • 在简单的项目中配置 Babel 会更容易,你只需要在 babel.config.json 中启用一个 compileJS: true 选项(或者它甚至可以在未来成为默认值 - 它不能是默认值,因为 @babel/eslint-parser 不编译源代码)

    ¥It will be easier to configure Babel in simple projects, you would only need to enable a compileJS: true option in babel.config.json (or it could even be the default in the future -- it can't be default as @babel/eslint-parser does not compile the source)

  • 它将确保插件版本与 @babel/core 版本同步,避免大多数由不匹配/不兼容的包版本引起的错误

    ¥It will make sure that the plugin versions are in sync with the @babel/core version, avoiding most of the bugs caused by mismatched/incompatible packages versions

  • 当我们迁移到 ESM 时,将很难在 transformSync 中同步解析和加载插件。这可以防止它成为问题。

    ¥When we move to ESM, it will be hard to resolve and load plugin synchronously in transformSync. This prevents it from being a problem.

@babel/core 中已经有 一个 RFC 为稳定的 ECMAScript 功能移动插件,这是朝这个方向迈出的第一步。

¥There is already a RFC to move plugins for stable ECMAScript features in @babel/core, which is the first step in this direction.

使用我们当前的 @babel/preset-env 架构,我们需要专门处理官方插件以根据 targets 自动启用或禁用它们。但是,这有两个缺点:

¥With our current @babel/preset-env architecture, we would need to specially handle official plugins to automatically enable or disable them based on targets. However, this has two drawbacks:

  • 特定插件的兼容性数据与插件实现完全分离(它甚至不是依赖,更像是内部隐式对等依赖:plugin -> @babel/core -> @babel/compat-data);

    ¥Compatibility data for a specific plugin is completely separated from the plugin implementation (it's not even a dependency, more something like an internal implicit peer dependency: plugin -> @babel/core -> @babel/compat-data);

  • 官方插件会得到 @babel/core 的特殊待遇,但我们要确保第三方插件具有与官方插件相同的功能。

    ¥Official plugins would get special treatment from @babel/core, but we want to make sure that third-party plugins have the same capabilities as official plugins.

继续开发 babel-polyfills 项目

¥Continue developing the babel-polyfills project

我们已经决定在 Babel 8 中从 @babel/preset-env 中删除旧的 core-js@2 支持。我们还想停止推广特定的第三方 polyfill,这可能会给我们的用户一种印象,即它是 Babel 本身的一部分。

¥We have already decided to remove the older core-js@2 support from @babel/preset-env in Babel 8. We also want to stop promoting a specific third-party polyfill, which might give our users the impression that it's part of Babel itself.

这可能以两种不同的方式发生:

¥This might happen in two different ways:

  • 我们只是在 Babel 8 中从 @babel/preset-env 中删除了 core-js@3,鼓励用户迁移到 babel-plugin-polyfill-corejs3(这是 @babel/preset-env 从版本 7.10.0 开始内部使用的)

    ¥We just remove core-js@3 from @babel/preset-env in Babel 8, encouraging users to migrate to babel-plugin-polyfill-corejs3 (which is what @babel/preset-env internally uses starting from version 7.10.0)

  • 我们可以在 @babel/preset-env 中保留 core-js@3 支持,但在我们移动转换插件时不能将其迁移到 @babel/core

    ¥We can keep core-js@3 support in @babel/preset-env, but not migrate it to @babel/core when we'll move the transform plugins.

无论我们采取哪种方式,当我们的用户需要更新其配置中的 core-js 集成时,我们都希望为他们提供至少一种替代方案。core-js 是一个非常好的 polyfill,可确保尽可能高的规范合规性,但用户可能更喜欢不同的权衡取舍。

¥Whichever path we take, we would like to offer at least one alternative to our users when they'll need to update the core-js integration in their configuration. core-js is a really good polyfill that ensures the highest possible spec compliancy, but users may prefer different trade-offs.

(Nicolò) 正在与 @ljharb 合作,以确保 @es-shims 项目 至少支持所有 ES2015+ 功能(我们实际上是针对 ES5+),以便 Babel 用户可以在至少两个选项之间自由选择。

¥(Nicolò) is working with @ljharb to make sure that the @es-shims project supports at least all the ES2015+ features (we actually aim for ES5+), so that Babel users are free to choose between at least two options.

这需要在放弃对 core-js@3 的内置支持之前发生,以便对 es-shims 感兴趣的人不必迁移两次。

¥This needs to happen before dropping built-in support for core-js@3, so that people interested in es-shims don't have to migrate twice.

扩展 targets 用于粒度转换

¥Expand targets usage for granular transforms

从一开始,@babel/preset-env 就使用 targets 选项来自动启用或禁用转换插件。

¥Since the beginning, @babel/preset-env has used the targets option to automatically enable or disable transform plugins.

但是,Babel 插件和浏览器中实现的功能之间并没有一对一的映射。

¥However, there isn't a 1-to-1 mapping between Babel plugins and features implemented in browsers.

例如,我们为不同的类字段类型(公共和私有、静态和实例)提供了一个插件,但浏览器有不同的兼容性矩阵:

¥For example, we have a single plugin for the different class fields types (public and private, static and instance), but browsers have varying compatibility matrices:

  • Firefox 73 和 Safari 14 仅支持公共实例字段

    ¥Firefox 73 and Safari 14 support only public instance fields

  • Firefox 75+ 支持公共实例和静态字段

    ¥Firefox 75+ supports public instance and static fields

  • Chrome 79+ 支持公共和私有字段,但不支持某些可选链接表达式中的私有字段

    ¥Chrome 79+ supports public and private fields, but doesn't support private fields in some optional chaining expressions

  • Chrome 84+ 完全支持私有字段,也支持私有方法

    ¥Chrome 84+ fully supports private fields, and also private methods

  • Safari TP 121 完全支持私有字段(即使是 ?.),但它不支持私有方法

    ¥Safari TP 121 fully supports private fields (even with ?.), but it doesn't support private methods

为每个功能创建一个插件是次优的。例如,我们可以将私有方法转换为私有字段,然后,如果需要,将它们转换为旧语法。但是,如果我们知道它需要被转译,我们可以通过直接将私有方法转换为旧语法而不需要中间步骤来生成更好/优化的输出。

¥Creating a plugin for each feature is sub-optimal. For example, we can convert private methods to private fields and then, if needed, convert them to older syntax. However, we can generate better/optimized output by directly converting private methods down to older syntax without the intermediate step if we know that it needs to be transpiled down.

从 Babel 7.13.0 开始,我们可以直接在插件中读取 targets 选项,我们可以修改我们的插件以自动执行给定 ECMAScript 功能的部分编译,这将在输出大小和运行时性能方面具有优势。

¥Since Babel 7.13.0, we can read the targets option directly inside a plugin, we can modify our plugins to automatically perform a partial compilation of a given ECMAScript feature, which would give advantages in the output size and runtime performance.

现有技术

¥Prior Art

这种方法并不是全新的。感谢与 @_developit 的合作,在 Babel 7.9.0 中,我们为 @babel/preset-env 引入了一个新的 bugfixes: true 选项。当启用该选项时,当使用 esmodules: true 作为编译目标时,我们只对 一些功能 进行部分编译。这是我们最初考虑这种可能性的原因,但当前的部分变换在使用更现代的目标(例如,defaults, not ie 11)时不太有用。

¥This approach isn't completely new. Thanks to a collaboration with @_developit, in Babel 7.9.0 we introduced a new bugfixes: true option for @babel/preset-env. When this option is enabled, and when using esmodules: true as the compilation target, we only partially compile some features. This what made us initially think about this possibility, but the current partial transforms are less useful when using more modern targets (for example, defaults, not ie 11).

我们也已经使用 targets 选项来决定在编译对象扩展时是否可以使用 Object.assign

¥We also already use the targets option to decide whether we can use Object.assign when compiling object spread or not.

动作要点

¥Action Points

这个目标可以分为两个可以并行完成的大任务:

¥This goal can be split into two big tasks that can be done in parallel:

  • 我们需要通过收集真实世界的浏览器列表查询并模拟未来流行查询(例如,defaults>2%, not dead)的发展方式,来确定这些优化在哪些方面有用。

    ¥We need to identify where these optimizations can be useful by collecting real-world browserslist queries and by simulating how popular queries (for example, defaults or >2%, not dead) will evolve in the future.

  • 我们需要实际实现必要的优化,确保它们仍然可以与其他插件一起正常工作(因为它们会大大增加可能的转换组合的数量)。

    ¥We need to actually implement the necessary optimizations, making sure that they still work well with the other plugins (since they would highly increase the number of possible transform combinations).

研究新的编译器 assumptions

¥Investigate new compiler assumptions

在 Babel 7.13.0 中,我们引入了一个新的顶层 assumptions 选项,以正式化 loose 模式选项的作用并为我们的用户提供更精细的控制(因为他们通常只能启用一些假设而不是全部假设)。

¥In Babel 7.13.0 we introduced a new top-level assumptions option, to formalize what the loose mode option does and offer more granular control to our users (since often they can only enable some assumptions and not all of them).

但是,我们只包含了在 loose 模式下编译时已经做出的假设的选项。我们现在可以调查我们的用户可能需要哪些新假设。

¥However, we only included options for assumptions we already made when compiling in loose mode. We can now investigate what new assumptions our users might need.

已经有一些建议,例如:

¥There are already some proposals, such as:

  • #8222 - 假设所有 ESM 导入实际上都是不可变的,从而避免了实时绑定所需的代码。

    ¥#8222 - assume that all the ESM imports are actually immutable, avoiding the code needed for live bindings.

  • #11356 - 假设编译类不扩展本地类,避免实例化可能的本地类所需的运行时性能成本。

    ¥#11356 - assume that compiled classes do not extends native classes, avoiding the runtime performance cost needed to instantiate possibly native classes.

我们可以通过以下方式找到我们应该实现的新假设:

¥We can find which new assumptions we should implement, by:

  • 手动检查我们编译到 "non-obvious" 输出的功能,这通常是由许多开发者不关心的边缘情况引起的。

    ¥Manually checking which features we compile to "non-obvious" output, which is usually caused by edge cases that many developers don't care about.

  • 征求社区的反馈,因为开发者可以测试哪些假设在他们的应用上有效,哪些无效。

    ¥Asking for feedback from the community, since developers can test which assumptions work and which don't on their applications.

彻底改造 Babel REPL

¥Overhaul the Babel REPL

Babel REPL 是学习 Babel 如何转译源代码的便捷在线运行。

¥The Babel REPL is a convenient playground to learn how Babel transpiles source code.

当前限制:

¥Current limits:

好有特点:

¥Features good to have:

  • AST Explorer(与现有的集成)

    ¥AST Explorer (integrate with existing one)

  • 具有完整堆栈跟踪的 stderr 作为错误日志

    ¥stderr with complete stack trace as error log

  • 标准输出作为输出

    ¥stdout as output

  • 从 UI 更改 Babel 版本

    ¥Change Babel version from UI

babel-website 中至少 15% 的开放问题与 REPL 相关:https://github.com/babel/website/issues?q=is%3Aissue+is%3Aopen+label%3Arepl

¥At least 15% of open issues in babel-website are related to the REPL: https://github.com/babel/website/issues?q=is%3Aissue+is%3Aopen+label%3Arepl

教育/调试工具

¥Educational/Debugging Tooling

与 REPL/ASTExplorer 相关,我们可以使用更多工具来帮助我们自己和第 3 方插件开发通用插件。这本质上是探索性的:AST 本身、调试等的不同可视化。

¥Related to the REPL/ASTExplorer, we could do with more tooling to help with general plugin development for ourselves and 3rd-party plugins. This is rather exploratory in nature: different visualizations for the AST itself, debugging, etc.

亨利一直在进行中的一些事情:

¥Some things already in progress Henry has been working on and off on:

  • 代码沙盒 用于制作与 https://astexplorer.net 相同的简单 Babel 插件,但具有自定义配置。

    ¥Codesandbox for making a simple Babel plugin in the same vein as https://astexplorer.net but with custom configs.

  • 输入到输出映射的 可视化 有助于理解 Babel 如何转换其代码。甚至对于让 JavaScript 用户熟悉新语法或特定转换演示的文档也很有用。

    ¥Visualization of input to output mapping to help understand how Babel transforms its code. Could be useful even for documentation in getting JavaScript users familiar with new syntax or a specific demo of a transform.

  • 测绘 的输入到输出就像一个源映射类型结构。可以做一个反向映射来找出是什么插件导致代码以某种方式输出,这有助于调试。

    ¥Mapping of input to output like a sourcemap type structure. Can do a reverse mapping to find out what plugin caused the code to be outputted a certain way which helps with debugging.

有关我们正在考虑的交互示例:https://babel-explorer.netlify.app/(在底部区域单击并按住鼠标!)

¥For an interactive example of what we are thinking about: https://babel-explorer.netlify.app/ (click and hold the mouse in the bottom sector!)