前端工程化之最强转译器 聊聊Babel杀手:SWC的野心与未来

简介: 前端工程化之最强转译器 聊聊Babel杀手:SWC的野心与未来

今天要讲的,就是当下最强转译器:SWC,以及它与目前前端生态中其他事物的联系。


kdy1、Vercel、Next.js 与 SWC


SWC 的全称是 Speedy Web Compiler。在Github 上面有 24k star。是由韩国程序员 kdy1 写的。kdy1 真名강동윤,他在 2017 年开始写 SWC,那一年他 20 岁,上大二。

2021 年,kdy1 加入了 Vercel 团队,SWC 也成了 Next.js 的默认转译器。

虽然 SWC 直到最近两年才火起来,但他已经在这方面投入了很多年。从这一点上,我们再次印证了一个道理:成功绝不仅仅是偶然!偶然的背后是无数努力付出得到的必然。


SWC 真的比 Babel 快那么多吗?


SWC 是用 Rust 这门语言写的。在它的官网上直接写着:在单核处理器的环境下,SWC 比 Babel 快 20 倍,如果是四核处理器,要快 70 倍。

Next.js 的转译器就是使用 SWC。不过在 Next.js 的实际环境下,只是比 babel 快不到 5 倍。原因是 Next.js 使用 Webpack 做打包器,除了 JavaScript 以外,还需要处理其他东西。

image.png

如果 Webpack 处理的东西非常多的话,SWC 在整体上的效果就更没有那么明显了。

下面是在一个真实的中大型项目中的测试。

image.png

可以看到将 Babel 切换到 SWC,在最终构建时只提升了大概 50% 的速度。

不过在开发时重新构建的时间提升了 3-4 倍,这是非常有意义的。


相比较 Babel,SWC 的缺点


虽然 SWC 在编译速度上确实很快,但是有些细节我们还需要注意。

SWC 的 transform 和 Babel 有些许差异,这是它们的差异列表

如果将一个 babel 项目贸然切换到 SWC 的话,可能需要特殊处理某些差异,否则可能会让浏览器的支持度降低。

SWC 也有插件体系,但是目前仍然是实验性的。

我们如果需要开发一个 SWC 的插件,首先要学习 Rust 和 WebAssembly,上手门槛明显很高。另外由于不支持 JS 的插件,所以等同于要把 Babel 生态中的插件全部用 Rust 翻译一遍,这明显是不可能的。

另外社区开发者有计划让 SWC 来支持 JavaScript 的插件,但是目前还未支持。

这是对应的讨论:github.com/swc-project…

因为如果要支持 JavaScript 插件,那么 Rust 就需要把 AST 传递给 JS。这个过程相当慢,因为它有两个瓶颈:

  1. 将 AST 以 JSON 结构从 Rust 传递到 JS 的成本。
  2. 使用 JS 的 JSON.parse 解析 JSON 的成本。

也有人尝试使用 JsBuffer 传递二进制序列化到 JavaScript 的缓冲区来解决这两个性能瓶颈。但是目前同样没有结果。

速度是 SWC 最大的优势,如果为了支持 JavaScript 插件而导致 SWC 本身变慢了,那么我们为什么不选择 Bable 呢?

并且 SWC 的维护团队暂时也没有支持 JavaScript 插件的打算。不过 kdy1 在这条 issue 中提到,SWC 2 将会支持 babel 插件。现在已经过去一年多了,SWC 仍然还有进入 2.x 版本。


SWC 与 Webpack


除了 SWC 自身的问题外,如果采用 Webpack 和 SWC 组合使用,我们还会遇到 Webpack 的一些问题。比如 Webpack 的某些 plugin 会在内部直接使用 Babel,比如 stylelint,这样会导致降低速度,并且无法避免。

而且 Webpack 自身的 JavaScript Parser 速度就很不理想。kdy1 就尝试联系 Webpack 的团队,让 SWC 作为 Webpack 的 JavaScript parser,但是有些困难,至今没有落地:github.com/webpack/web…


SWC Minify 和 Terser


除了 SWC 自身以外,它还提供了 SWC Minify 来压缩代码。

它的竞争对手是 Terser。

目前来看,SWC Minify 的性能会比 Terser 快 25% 左右,但是压缩后的代码体积会比 Terser 大 1.2-2.3%,有些得不偿失。

不过这个数据还是很不错的,毕竟 Terser 已经存在了很多年,而 SWC Miniify 是一个新的东西,在未来还会有一定的进步空间,来提升更高的压缩率。


SWC 与 TypeScript


如果要使用 TypeScript 的话,那么 SWC 的对象就将会是 tsc。

tsc 的性能瓶颈是 type check,要打破这个瓶颈,有两个方向可以考虑:

  1. 利用多线程的能力,但是 TypeScript 团队不太关注这个功能。github.com/microsoft/T…
  2. 换一种性能更好的语言去重新实现一个 type cheker。当然 TypeScript 团队也不同意这个方案。

kdy1 上个月在推特上面说他正在尝试用 Go 来重写 type cheker。

image.png

他还写了一篇文章来解释为什么要使用 Go 而不是 Rust

总结来说就是 tsc 会大量使用共享变量,但是 Rust 不支持这种行为,所以用 Go 会更合适。


SWC、babel 和 esbuild 到底谁更快?


聊了这么多,我想直观的给你展现一下,SWC 到底有多快。

于是我花了几个小时做了个网站,你可以去尝试一下。

www.webbuild.me/

这个网站可以直观的对比使用各种编译工具对各种语言的进行编译的速度。

image.png


ES6 转译 ES5


由于 esbuild 不支持转译到 es5,所以我只对 SWC 和 babel 进行比较。

考虑到性能波动和缓存等问题,我会转换五次,取平均值。

babel:309ms 212ms 188ms  219ms 197ms。

swc:52ms 7ms 12ms 8ms 13ms。

babel 的平均值是 225 ms,swc 的平均值是 18.4 ms。快了将近 12 倍。


TS 转译 ES6


esbuild 是支持 ts 转译 es6 的,所以这次对三者进行比较。

老样子,同样转译 5 次,取平均值。

babel:55ms 37ms 16ms 23ms 15ms。

swc:6ms 2ms  6ms 1ms 1ms。

esbuild:3ms 4ms 4ms 7ms 2ms。

平均值:babel 29.2ms、swc 3.2ms、esbuild 4ms。

swc 和 esbuild 相差不多,但 swc 更胜一筹。babel 同样和它们不在一个层次上。


TS 转译 ES5


由于 esbuild 不支持编译到 ES5,所以这一轮只比较 babel 和 swc。

babel:104ms 41ms 45ms 41ms 40ms

swc:9ms 1ms 1ms 1ms 2ms

平均值:babel 54.2ms、swc2.8ms。


线上环境下的测试


上面的数据是在我本机使用一台 M1 的 MacbookPro 运行的,如果在线上运行,速度可能会更慢。

网站被我部署在 vercel 上面,下面是几组线上环境的数据。

es6 转译 es5,babel 基本上都在 600ms 左右,而 swc 只需要 10 ms。这样看来,在某些环境下,SWC 的性能相比较 Babel 确实有 60 倍左右的差距。

ts 转译 es6,babel 基本上都在 20ms-50ms 之间波动,偶尔会高达 100 多 ms,swc 基本上都在 1ms,esbuild 基本上在 1-2ms 之间。

ts 转译 es5,babel 最低在 30ms 左右,swc 最低只需要 1ms。

三轮性能比拼,基本上 SWC 完胜;esbuild 比 SWC 稍慢一丢丢;babel 完败。


kdy1 的野心和 SWC 的未来


kdy1 的野心并不小。

在他的计划里,他要在 SWC 中做好四个东西:

  • ✅ 转译器 (替代 Babel)
  • 🚧 类型检查器 (替代 tsc)
  • 🚧 压缩器 (替代 Terser)
  • 🚧 打包器 (替代 webpack)

虽然目前他只完成了一个。

在我的印象里,韩国程序员大神并没有那么多。但是 kdy1 让我想起来 N 年前 LOL 里面的天才韩国少年大魔王李相赫,哈哈。

而他的东家,Vercel,也需要世界上最好的编译工具,所以它会给 kdy1 提供可以大展身手的空间和平台。


总结


目前在生产环境使用 SWC,过于担心浏览器兼容性的话,仍然需要注意转译的细节。不过大部分情况下,SWC 的转译结果已经和 Babel 没什么区别了。

对没有那么复杂的项目,我仍然建议使用 Babel,Babel 虽然在速度上有着不可弥补的语言劣势,但是它自身的架构非常健壮,生态也非常成熟。这些都是目前所有转译器在未来很长一段时间内都无法追赶的。

对于复杂的项目而言,考虑到构建过程的综合因素,不要抱有对 SWC 太高的预期。比如你的项目中包含了大量各种样式、图片、文本、多媒体等其他资源,那么 SWC 对你的项目整体构建速度的提升是很有限的。但如果你的项目是一个以 JavaScript/TypeScript 为主的项目,那么提升将会是巨大的。

综合来看,SWC 已经很优秀了,不过它还有很长的路要走,但可以预料,未来它在构建工具领域的成就绝不会亚于 Webpack 和 Babel。

如果你对前端工程化感兴趣,欢迎关注我的深入浅出前端工程化专栏。

后续我还会解析 npm、yarn、pnpm、cnpm、verdaccio、babel、webpack、rollup、parcel、gulp、grunt、vite、esbuild、yeoman、plop、hygen、slush、cra、browserify、tsc、flow-bin、terser、uglify、minify、lerna、nx、turborepo、rush、bolt、oao、bit、core-js、regenerator-runtime、whatwg-fetch、es5-shim、es6-shim、js-polyfills 等前端工程化相关的技术。



相关文章
|
4月前
|
前端开发 测试技术 持续交付
版本控制和团队协作:前端工程化的关键要素
版本控制和团队协作:前端工程化的关键要素
|
4月前
|
前端开发 JavaScript 测试技术
探索现代前端工程化工具与流程:提升开发效率和项目质量
探索现代前端工程化工具与流程:提升开发效率和项目质量
探索现代前端工程化工具与流程:提升开发效率和项目质量
|
4月前
|
前端开发
构建工具对比:Webpack与Rollup的前端工程化实践
在现代前端开发中,前端工程化变得愈发重要。本文将对两个常用的构建工具——Webpack和Rollup进行比较,探讨它们在前端工程化实践中的特点、优势和适用场景。无论是大型应用的打包优化还是轻量级库的构建,选择适合的构建工具都能提高开发效率和项目性能。
29 1
|
7月前
|
前端开发 JavaScript 数据可视化
前端工程化知识系列(10)
前端工程化知识系列(10)
53 0
|
7月前
|
缓存 前端开发 JavaScript
前端工程化知识系列(8)
前端工程化知识系列(8)
32 0
|
4月前
|
自然语言处理 前端开发 测试技术
前端工程化最佳实践:项目结构、代码规范和文档管理
前端工程化最佳实践:项目结构、代码规范和文档管理
|
5月前
|
JavaScript 前端开发 C++
Javaweb之前端工程化的详细解析(2)
3.2.2.3 运行vue项目 那么vue项目开发好了,我们应该怎么运行vue项目呢?主要提供了2种方式 第一种方式:通过VS Code提供的图形化界面 ,如下图所示:(注意:NPM脚本窗口默认不显示,可以参考本节的最后调试出来)
53 0
|
5月前
|
存储 JavaScript 前端开发
Javaweb之前端工程化的详细解析(1)
3 前端工程化 3.1 前端工程化介绍 我们目前的前端开发中,当我们需要使用一些资源时,例如:vue.js,和axios.js文件,都是直接再工程中导入的,如下图所示:
50 0
|
2月前
|
Web App开发 JavaScript 前端开发
前端工程化
前端工程化
40 4
|
3月前
|
前端开发 JavaScript Java
让我们来聊聊前端的工程化
让我们来聊聊前端的工程化