分类
前端工具链

初试 SWC(Speedy Web Compiler)

SWC 是一个用 Rust 写的编译工具,功能跟 babel 很类似。它的优势在于速度,按照官网所说,在单核上它的速度是 babel 的 20倍,四核上是 babel 的 70 倍。

我最近尝试升级工具链,第一步是使用 esbuild-loader 替代 babel-loader,比较顺利。但是 esbuild 只支持 ES2015,为了支持 IE11,我们还需要再转译一次。这次我想试试 SWC。

安装与配置

安装 swc 很简单。我打算 build 的时候用 @swc/cli 转译;debug IE11 的时候把 swc-loader 套在 esbuild-loader 前面输出。所以需要安装三个包:

nom i @swc/core @swc/cli swc-loader -D

接下来添加配置文件 .swcrc

{
  "sourceMaps": false,
  "module": {
    "type": "umd"
  },
  "minify": true
}

默认目标平台 target: 'es5',不需要再写。其它语言选项也走默认即可。

SWC sourceMap 支持三种配置:truefalseinline,意思一看就明白。但目前 bug 比较多,即使设置 sourceMap:false,也只是不生成 sourcemap 文件,对应的链接标记仍然会生成。

module.type 有另一个 bug:即使目标平台是 ES5,它也会使用 ESM 引入依赖,导致语法解析出错。比如代码中使用了 async function,SWC 转译时就需要 import regeneratorRuntime from 'regenerator-runtime'。所以上面我配置 module.type"umd",一方面避免错误的 ESM import,另一方面可以通过全局方式引用这些库。

minify: true 表示我们希望 SWC 转译代码时顺便把它们压缩一下。官方文档说这个功能还不是很完善,不过我暂时没发现明显的问题。

swc 游乐场

SWC 官方提供预览网站:SWC Playground – SWC。我们可以把源码贴上去,查看编译结果。也可以调整选项,看看不同选项对结果的影响。

问题

把 SWC 放进工具链的过程还算顺利,不过接下来使用的时候却遭遇了不少问题。

首先就是上文说的 ESM 导入的问题。默认情况下 SWC 会 import 'regenerator-runtime',这个问题必须解决。考虑到这个代码特征比较明显,起初,我打算直接字符串过滤掉。后来翻了文档,又在 playground 里尝试了一下,发现 UMD 应该可以解决问题。

然后是语法问题。下面这段代码 SWC 编译错误:

// 输入
let a = 10;
for (let b = 0; b < a; b++) {
    let c = 0, b = 10, d = 100;
    console.log(b);
}

// 输出
var a = 10;
for (var b = 0; b < a; b++) {
    var c = 0, b = 10, d = 100;
    console.log(b);
}

这段代码其实有点意思,我看了很久才找到问题:let 声明变量时,for () 相对于下面的代码块,是上级 context;而 var 时,它们处于同级 context。所以下面这段循环只会运行一次,而不是像上面一样,执行 10 次。

(这段代码很能考察 letvar 的不同,我准备把它加入我的面试题库。)

还有其它一些语法问题,因为上面这个问题无法绕过,意味着使用 SWC 这条路不可行,所以我也没有深入研究,就不一一列举了。

总结

SWC 用户量太小,未知 Bug 很多;开发团队不大,又是用 Rust 写的,也给想贡献代码的前端社区带来很大阻碍。所以目前还难以应对大型项目、工业级别的需求。

不过它的速度的确很快,对改进项目构建速度有很大帮助。希望那些 bug 能尽快修复,我们可以早点把它应用到产品当中。

meathill

爱编程,爱旅游,爱吐槽。
今年的目标是完成并运营至少一个 Side Project。
《Electron + Vue 实战开发》龟速创作中……

“初试 SWC(Speedy Web Compiler)”上的一条回复

欢迎吐槽,共同进步

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据