30

Babel 7.0正式发布,支持TypeScript,JSX Fragment

 5 years ago
source link: http://www.infoq.com/cn/news/2018/08/babel7-published?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

今天,Babel 官方博客宣布正式推出 Babel 7.0,在过去两年内,Babel 7 经历了 4000 次提交,发布了 50 多个预览版本,这也是三年前发布 v6.0 之后的最大更新。

Babel 的重要意义

由于 JavaScript 在不断地发展,各种新标准和提案也就层出不穷,用户使用的浏览器也不同(尤其是旧版的 IE),这就导致了有些用户无法使用 JavaScript 的一些新特性,如果开发人员想使用新的语法(如 class A {}),在旧浏览器上就会因为这个问题出现 SyntaxError。

由于它能够转换 JavaScript 代码,还可用于实现新功能,因此它已成为 TC39 获取社区对 JavaScript 反馈的重要桥梁。

如今,Babel 是 JavaScript 开发的基础。它在 npm 上,每月有 1700 万次的下载量,用户包括主流框架(React,Vue,Ember,Polymer)的开发者和企业(Facebook,Netflix,Airbnb)。即使你自己没有使用它,你的依赖项也很可能正在使用 Babel。

Babel 由志愿者驱动

虽然 Babel 对 JavaScript 语言的未来,甚至对社区和 js 生态都产生了巨大的影响,但你肯定想不到,他们的维护者只是由社区的几个志愿者组成。

16471-1535642314905.jpg

重大变更

  • 不再支持不在维护中的 Node 版本:0.10、0.12、4、5;

  • 使用 @babel 命名空间,因此 babel-core 就变成了 @babel/core;

  • 移除(并停止发布)任何年度预设(preset-es2015 等),@babel/preset-env 取代了对这些内容的需求 ;

  • 移除“Stage” 预设(@babel/preset-stage-0 等),同时移除了 @babel/polyfill 中的提议;

  • 重命名了某些包:任何 TC39 提议插件现在都是 -proposal 而不是 -transform,所以 @babel/plugin-transform-class-properties 变成了 @babel/plugin-proposal-class-properties;

  • 针对某些面向用户的包(例如 babel-loader、@babel/cli 等)在 @babel/core 中引入 peerDependency;

babel-upgrade

babel-upgrade 是一个用于进行自动升级的新工具:目前在 package.json 和.babelrc 配置文件中配置了依赖关系。

建议直接在 git 仓库上运行 npx babel-upgrade,或者使用 npm i babel-upgrade -g 进行全局安装。

如果你想修改文件,可以使用参数 --write 和 --install。

JavaScript 配置文件

Babel 7.0 引入了 babel.config.js。

*.js 配置文件在 JavaScript 生态系统中相当常见。ESLint 和 Webpack 分别使用了.eslintrc.js 和 webpack.config.js 配置文件。但这并不意味着它们就取代了.babelrc 或 package.json,这不是必要条件,但在某些情况下这可能很有用。以下是仅在“生产”环境中使用插件进行编译的配置。

babel.config.js 的配置解析方式与.babelrc 不同。它始终会解析该文件中的配置,而不会从每个文件向上查找,直到找到配置为止。这样就可以利用 overrides 特性。

使用 overrides 进行选择性配置

有些应用程序需要针对测试、客户端代码和服务器代码使用不同的编译配置选项,通过这种方式就不需要在每个文件夹下创建.babelrc 文件了。

速度

Babel 团队做了很多变更来优化代码,并接受了来自 V8 团队的一些补丁( https://twitter.com/rauchg/status/924349334346276864 )。

输出选项

Babel 支持预设和插件选项有一段时间了。比如,你可以将插件包装在一个数组中,并将选项对象传给插件:

Babel 团队还对部分插件的 loose 选项做了一些修改,并为部分插件添加了一些新选项!

比如,对于类 class A {},现在不包含 _classCallCheck。

如果 for-of 循环的是一个数组,那么可以使用这个新选项:[“transform-for-of”,{“assumeArray”:true}]

在 loose 模式下将 transform-typeof-symbol 插件排除在外。

“纯粹”的注解支持

转换后的 ES6 类使用/*#__PURE__*/进行注解,这样就可以告诉 Uglify 和 babel-minify 移除死代码。这些注解也被添加到其他辅助函数中。

TC39 提案支持

以下是 Babel 支持的一些新语法以及已经添加到 v7 中的语法清单:

  • ES2018:Object Rest Spread (var a = { b, ...c })

  • ES2018(新):Unicode 属性正则表达式

  • ES2018(新):JSON 超集

  • ES2015(新):new.target

  • 阶段 3(新):类私有实例字段(class A { #b = 2 })

  • 阶段 3(WIP):静态类字段、私有静态方法(class A { static #a() {} })

  • 阶段 3(新):可选 Catch 绑定 try { throw 0 } catch { do() }

  • 第 3 阶段(新):BigInt(仅限语法)

  • 第 3 阶段:动态导入(import("a"))

  • 第 2 阶段(新):import.meta(仅限语法)(import.meta.url)

  • 第 2 阶段(新):数字分隔器(1_000)

  • 第 2 阶段(新):function.sent

  • 第 2 阶段:export-namespace-from(export * as ns from'mod'),从 export-extensions 中拆分出来

  • 第 2 阶段:装饰器

  • 第 1 阶段:export-default-from(export v from 'mod'),从 export-extensions 中拆分出来

  • 第 1 阶段(新):可选链接(a?.b)

  • 第 1 阶段(新):逻辑赋值(a &&= b; a ||= b)

  • 第 1 阶段(新):Nullish Coalescing(a ?? b)

  • 第 1 阶段(新):管道操作符(a |> b)

  • 第 1 阶段(新):throw 表达式(() => throw new Error("a"))

TypeScript 支持

Babel 团队与 TypeScript 团队合作,让 Babel 使用 @babel/preset-typescript 解析 / 转换类型语法,类似于使用 @babel/preset-flow 处理 Flow 的方式。

之前(有类型):

之后(移除了类型):

JSX Fragment 支持(<>)

正如 React 博客中所提到的,从 Beta.31 开始,已经支持 JSX Fragment。

Babel 辅助函数的变化

@babel/runtime 已经被分为 @babel/runtime 和 @babel/runtime-corejs2。前者仅包含 Babel 的辅助函数,后者包含辅助函数以及 polyfill 函数(例如 Symbol、Promise)。

规范规定了需要通过 new Person() 实例化一个类,但如果它被编译成一个函数,就可以直接调用 Person(),所以他们提供了一个运行时检查。

使用 @babel/plugin-transform-runtime 和 @babel/runtime(作为依赖项),Babel 可以提取单个函数,而且只需要模块函数来获得较小的输出,如下所示:

自动 polyfill(实验性质)

要使用 polyfill,只需导入 @babel/polyfill 即可:

但这样会导入整个 polyfill,如果浏览器已经支持某些特性,就不需要导入所有内容。可以使用选项 useBuiltins:”entry”来导入需要用到的部分。

可以更进一步,通过选项 useBuiltIns:”usage”只将需要用到的 polyfill 导入到代码库中。

它将遍历每个文件,并在每个使用了内置 polyfill 的文件的顶部注入一个导入语句。例如:

但它的推理不是很完美,可能会出现误报:

Babel 宏

Babel 的一大特点是它的可插拔性。多年来,Babel 从一个“6to5”编译器转变为代码转换平台,为用户和开发人员提供了出色的优化选项。人们已经为特定库和用例开发了大量的 Babel 插件,用以提升库 API 的性能和功能。

可惜的是,将这些插件添加到代码库中需要更改配置,从而增加了代码复杂性。由 Kent C. Dodds 开发的 babel-plugin-macros(https://github.com/kentcdodds/babel-plugin-macros)已经解决了这个!

在安装了 babel-plugin-macros 并将其添加到配置中(它已包含在 create-react-app v2 中)之后,你就不必费心配置就可以使用宏了。此外,为特定应用程序或代码编写自定义转换也变得更加容易。

模块目标

Babel 一直试图在转换的影响范围和功能之间做出平衡。在 Babel 7 中,通过配置 Babel 来支持模块 / 非模块模式变得更加容易。

值得注意的是,一些流行的 Web 框架的 CLI 工具已经在利用这些支持,这让转换后的 JavaScript 代码减少了大约 20%。

class C extends HTMLElement {}

Babel 总是会警告说它不支持扩展原生内置元素(Array、Error 等),但现在可以了!Babel 团队对类插件进行了修改,如果你使用了 preset-env,那么默认就自动启用了这个特性。

网站变更

Babel 网站从 Jekyll(https://jekyllrb.com/)搬到了 Docusaurus(https://docusaurus.io/)。

REPL

1retr1-1535642315502.jpg640?wx_fmt=png

Babel 将 REPL 重写为 React 组件,并更好地与 CodeSandbox 集成。这样你就可以在 REPL 中安装来自 npm 的任何插件或预设,并获取 CodeSandbox 的任何更新。

接下来要做什么

Babel 本质上就是要与 JavaScript 紧紧联系在一起,包括在语法变得“稳定”之前花时间和精力来实现和维护语法。Babel 团队关心的是整个过程:升级路径、新特性的传播、标准 / 语言设计的教学、易用性以及与其他项目的集成。

在 Nicolò的帮助下,Babel 团队几乎完成了新的装饰器的实现。这是一个漫长的旅程,因为新的提案完全不同,而且比旧的更强大。它可能会在下一个次要版本中发布。

还有很多新特性还在开发当中:插件顺序、更好的验证 / 错误、速度提升、新的 loose/spec 选项、缓存、异步使用 Babel、从 CI 构建、冒烟测试、运行 test262。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK