🔥你应该了解的SWC: Speedy Web Compiler

一提起 Babel 相信大家都不会陌生,你的 javascript compiler,但是自从 Rust 大火以后,前端生态也发生了天翻覆地的变化,我们这次聊的就是重大的变化之一。

一个或许比 Babel 更优的选择

而事实上,很多你所熟知的开源库和框架都在拥抱 SWC

here we go!

更多信息请移步⬇️ SWC的官网 https://swc.rs/

本篇文章我会以《怎么基于SWC开发去掉代码中console.logjsdemo》的视角来带你领略 SWC 的魅力

⚠️ 阅读本文的前置知识:

  • AST(Abstract Syntax Tree):抽象语法树
  • Compiler pipeline:编译的一个基础工作流(SWC还有一个 minify 的 pipeline)
  • Node fs system:Node 的文件系统(一丢丢就好)

image

正文开始👉


什么是 SWC 📌

SWC是一个可扩展的基于Rust的平台,用于下一代快速开发工具。它被Next.js、Parcel和Deno等工具以及Vercel、字节跳动、腾讯、Shopify等公司使用。 SWC可用于编译和打包。在编译方面,它接收使用现代JavaScript特性编写的JavaScript/TypeScript文件,并输出符合所有主流浏览器支持的有效代码。 SWC is 20x faster than Babel on a single thread and 70x faster on four cores.

开始 📌

  • 先打开 bash 窗口,创建一个项目目录,并用 VSCode 启动项目

carbon

  • 接着安装依赖 @swc/core

image

  • 接着创建 src 目录,并创建 input.js,和 swc.js,创建完成后的目录如下

image

  • 然后在 input.js 中输入以下代码,作为后续的源代码

carbon

  • 接着在 swc.js 中输入以下代码,引入的 @swc/corefs 模块

carbon

  • 接着我们可以先分别感受一下 transformparse 2个过程

parse 添加代码如下:

carbon

node swc.js 输出如下:

image

这里我想单独说一下这就是解析出来的 Abstact Syntax Tree

  • type: 'FunctionDeclaration'

    表示这是一个函数声明的节点类型。

  • identifier: { ... }

    这是函数声明的标识符,其中包含着名字、起始位置(就是那个 span)等信息。(如果你觉得不够清晰,可以 JSON.stringify(AST, null, 2) 输出看看)

  • declare: false

    表明此函数声明不是一个类型声明。

  • params: []

    表示函数参数为空数组,即此函数没有参数。

  • decorators: []

    函数装饰器列表为空数组,即此函数没有装饰器。

  • span: { start: 1, end: 100, ctxt: 3 }

    表示此函数声明在源代码中所占据的位置范围。

  • body: { ... }

    表函数体其中包着函数的抽语法结构

  • generator: false

    表示此函数不是一个 generator 函数。

  • async: false

    表示此函数不是一个异步函数。

  • typeParameters: null

    表示此函数没有指定类型参数。

  • returnType: null

    表示此函数没有指定返回类型。


okk~ 简单解释了一下 AST,我们继续 ↩️

transform 添加代码如下:

carbon

node swc.js 输出如下:

image


感受完了这俩步骤之后,我们开始来实现删除 console.log (如果你好奇为啥是这两步,请回看前置知识那里的图)

⚠️ 这里需要解释一下:

SWC 是基于 rust 语言实现的,而且swc团队也希望你用 rust,因为这样会获得更强的性能,所以你想要真正开发插件,请用 rust 语言编写,并参考 swc 的官方文档

这篇文章旨在带你感受一下 SWC,主要目的是介绍它,所以我们这里用正则给出一个简单的 js demo 的实现:

const swc = require('@swc/core')
const fs = require('fs')
 
// transform output code
async function transformCode(code) {
  const output = await swc.transform(code, {
    isModule: true,
    jsc: {
      parser: {
        syntax: "ecmascript"
      }
    }
  })
  return output
}
 
// generate AST
async function generateAST(code) {
  const module = await swc.parse(code, {
    syntax: "ecmascript",
    comments: false,
    script: true,
    target: 'es3',
    isModule: false,
  })
  return module
}
 
const code = fs.readFileSync('src/input.js', "utf-8")
 
async function removeConsole() {
  const {code} = await transformCode(code)
  return res.replace(/console\.log\(.*?\);?/g, "")
}
 
removeConsole().then(ret => console.log(ret))

执行 node swc.js

不出意外你会在控制台看到以下输出:

image

到此我们也就实现了删除 console.log

⛔ ps:特别警告小机灵鬼们,别拿这个方案去混kpi哈!你会被开除的!相信我!因为正常情况会以DFS即深度优先的遍历的方式去遍历每一个节点,来做相应的操作,而事实上swc也实现了visitor去帮你遍历节点,但是似乎仅支持 rust,果然是性能优先,哈哈哈😁。

2023/12/01 patch: 我发现一个库ast-grep如果你还是想用js的话,或许可以试试这个,希望它会有用,不过我没有试过哟,我是看别人用来做Vue3的jsx功能。这个库@vue-macros/cli就是基于ast-grep开发的。

b88ad5d8c6704d1d4872f389e727fd8


😊okk~ 快去尝试为你的团队构建基于 swc 的生态工具吧~ 记得是参考官网用 rust 编写哦~