16

swc-node, 最快的 TypeScript/JavaScript compiler

 3 years ago
source link: https://zhuanlan.zhihu.com/p/165485522
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.

swc-node, 最快的 TypeScript/JavaScript compiler

Frontend at day, Rustacean at night.

2020.09.17 更新

swc-node/core 的异步 API 性能已经基本与 esbuild 持平了,大部分场景下略微慢 10% 以内,作者还在非常用力的优化性能,预计不久的将来性能会有一波质的提升。

2020.08.01 更新

昨天

提醒我,esbuild 的同步 API (transformSync) overhead 挺大的,我去看了下源码然后又用异步 API (transform)测试了一下, esbuild 的异步 API 大概是 @swc-node/core 的 5 倍左右性能,而且 CPU 占用更少。

但是 @swc-node/core 还是有实际意义的。就以 jest 为例,jest 的 transformer 只能使用同步的 API,这种场景下 @swc-node/core 依然是最快的选择。

如果大家对 deno 有所关注会发现 deno 围绕 TypeScript 生态扩展了很多用 Rust 实现的高性能工具链,比如 deno_lint 和 deno_fmt。

而这些工具链都是建立 swc-project/swc 项目上,swc 是用 Rust 实现的一套 TypeScript/JavaScript compiler,性能较 babel/ts 快 5~20 倍。

swc 官方提供了 node binding,但是官方版本使用起来有几个问题:

  • 使用 neon 来实现 NodeJS 的 binding,neon 在 binding 层性能相较于 NodeJS 的 n-api 有一定的劣势,并且不是 ABI stable。这意味着针对多个 Node/V8 版本要编译多个 binary。
  • prebuilt 的 binary 在 postinstall 的时候从 Github assets 下载进行分发,在 +86 地区会被 GFW 制裁。
  • 在 native 层做了太上层的抽象,(Class 封装,参数的一层层 serialize/deserialize)进一步降低了性能。

为了解决这些问题,诞生了 swc-node 项目:

https://github.com/Brooooooklyn/swc-node​github.com

与官方的 @swc/core 相比,swc-node 有以下几个优势:

  • 使用 n-api 实现,兼容 8.9+ 所有的 NodeJS 版本
  • 没有 postinstall,所有的内容都最小化的从 npm 下载,很方便的使用各种 npm 源加速
  • 对 node 各种生态有更好的支持,比如 jestswc-register (未来还会有 swc-loader 等其它工具链的支持)

在性能上,Github 的项目中有一个简单的 benchmark,将 RxJS 的 AjaxObservable.ts 编译成 ES2015 + CommonJS 的 JavaScript(这里不用 ES5 target 是因为 esbuild 不支持 target ES5):

@swc-node/core x 151 ops/sec ±3.74% (77 runs sampled)
@swc/core x 107 ops/sec ±0.51% (78 runs sampled)
esbuild x 52.89 ops/sec ±1.58% (67 runs sampled)
typescript x 21.08 ops/sec ±9.68% (40 runs sampled)
Transform rxjs/AjaxObservable.ts benchmark bench suite: Fastest is @swc-node/core

而使用 @swc-node/jest 之后,我目前在公司负责的一个纯 TypeScript 项目测试运行时间也大大降低:

// jest.config.js

module.exports = {
  verbose: true,
  transform: {
    '^.+\\.(t|j)sx?$': '@swc-node/jest',
  },
}

ts-jest:

Test Suites: 48 passed, 48 total
Tests:       239 passed, 239 total
Snapshots:   49 passed, 49 total
Time:        49.808 s
Ran all test suites.
✨  Done in 54.35s.

@swc-node/jest:

Test Suites: 49 passed, 49 total
Tests:       250 passed, 250 total
Snapshots:   53 passed, 53 total
Time:        9.921 s
Ran all test suites.
✨  Done in 15.79s.

虽然 swc 又快又好,但是还是有一些毛病的,在使用之前你需要有一些取舍:

编译产物还没有经过大规模验证:

由于是从零开始编写的 TypeScript 编译器,swc 毕竟被使用的时间还太短了,在我接入公司项目的过程中就发现了好几个编译 bug,所以目前不推荐用来编译生产环境代码,用在 dev 环境或者用来编译测试代码都是不错的选择。

@swc-node 项目中,如果使用过程中发现编译有问题的文件,可以通过 fallbackToTs 选项让特定的文件 fallback 到 TypeScript 编译。

目前只支持 linux-gnu-64/ macOS / Win 64 三个平台

如果你想在 Android 设备,linux musl 环境或者 Windows ARM 上使用 @swc-node 可能需要等上一段时间了

招聘时间:

我所在的团队是字节跳动 IES 的前端架构团队,团队方向是前端性能/体验/监控,对接的业务都是 DAU 吓死人我从来没见过的量级。

如果你对前端的性能/体验/监控或者工程化感兴趣,可以直接通过 https://job.toutiao.com/s/Jjd16j5 直接投递简历,也可以先加我微信我们先聊聊: Brooooooklyn - Overview


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK