SWC
SWC
SWC 英文全称为 Speedy Web Compiler,是一个基于 Rust 的可扩展平台,用于下一代高速开发工具。它被 Next.js、Parcel、Deno 等工具,以及 Vercel、字节跳动、腾讯、Shopify 等公司广泛使用。
SWC 既可以用于编译,也可以用于打包。在编译方面,它接受使用现代 JavaScript 功能的 JavaScript / TypeScript 文件,并输出由所有主流浏览器支持的有效代码。
特点
SWC 的主要特点就是快。当只使用一个 CPU 核心(即单线程环境)时,SWC 比 Babel 快 20 倍,而当使用四个 CPU 核心(即四核环境,能够进行并行处理)时,SWC 比 Babel 快 70 倍。
SWC 对标的就是 Babel,力图成为 Babel 的替代品。而 SWC 之所以可以那么快,主要是由于以下几个因素:
- 编程语言:SWC 是用 Rust 语言编写的。Rust 是一种系统编程语言,它旨在提供内存安全性,无数据竞争,并且有着高效的性能。Rust 的执行速度通常比 JavaScript 快。
- 并行处理:Rust 具有优秀的并行处理和并发能力。当在多核 CPU 上运行时,SWC 能够有效地利用这些核心并行执行任务,从而大大提高了处理速度。
- 优化的设计:SWC 设计上对性能进行了优化。例如,它使用一次性遍历(single-pass traversal)来转换代码,这种方法比 Babel 使用的多次遍历更高效。
- 跳过不必要的工作:与 Babel 不同,SWC 可以跳过一些不必要的工作,例如不需要生成和处理 source maps,除非明确需要。
早期各种前端工具都是基于 Node.js 来写的,Node.js 本身只是一个 JS 的运行时,JS 本身又是一门单线程解释语言,所以 JS 的运行速度不会比像 Rust、Go 这种语言快。
近几年开始有一种趋势,用其他的编程语言来编写前端工具,甚至还专门出现了一个词语 rustification(锈化),就是指使用 Rust 语言来翻新已有的前端工具,从而提升工具的性能。
- SWC:使用 Rust 编写的超快速的 JavaScript/TypeScript 编译器。它的目标是替代Babel。
- Turbopack:Vercel 声称这是 Webpack 的继任者,用 Rust 编写,在大型应用中,展示出了 10 倍于 Vite、700 倍于 Webpack 的速度。
- esbuild: esbuild 是由 Go 编写的构建打包工具,对标的是 webpack、rollup 和 parcel 等工具,在静态语言的加持下,esbuild 的构建速度可以是传统 js 构建工具的 10-100 倍,就好像跑车和自行车的区别。
- Rome: 是一个使用 Rust 编写的全栈工具链,它打算整合各种前端开发工具的功能,从而提供一个统一的、一体化的开发体验。Rome 的目标是替代或集成诸如 Babel、ESLint、Webpack、Prettier、Jest 等多个分散的工具。
- Deno: 是一个使用 Rust 和 TypeScript 编写的 JavaScript/TypeScript 运行时,它的目标是成为一个更安全、更高效的 Node.js 替代品。
API
SWC 提供了相应的 API:
yarn add @swc/core -D
const swc = require("@swc/core");
const fs = require("fs");
const path = require("path");
const codePath = path.resolve("src", "index.js");
const sourceCode = fs.readFileSync(codePath, "utf8");
const outDir = path.resolve(__dirname, "dist");
swc
.transform(sourceCode, {
jsc: {
target: "es5", // 设置目标JavaScript版本
parser: {
syntax: "ecmascript", // 设置源代码的语法
},
},
})
.then((res) => {
// console.log(res.code)
if (!fs.existsSync(outDir)) {
fs.mkdirSync(outDir);
}
const outputFilePath = path.join(outDir, "index.js");
fs.writeFileSync(outputFilePath, res.code);
})
.catch((err) => {
console.error(err);
});
CLI
SWC 也提供了 CLI 工具:
yarn add @swc/cli -D
npx swc ./file.js
npx swc ./file.js -o output.js
npx swc ./my-dir -d output
配置对象
在使用 transform 方法时,第二个参数就是一个配置对象,支持多种配置项。
如果没有配置文件,那么会有一个默认的配置设置:
{
// 这个配置项用于设置 JavaScript的 编译选项
"jsc": {
// 这个配置项用于设置解析器的选项
"parser": {
// 设置源代码的语法,可以是 ecmascript、jsx、typescript 或 tsx
"syntax": "ecmascript",
// 是否启用JSX语法
"jsx": false,
// 是否启用动态 import() 语句
"dynamicImport": false,
// 是否启用私有方法和访问器
"privateMethod": false,
// 是否启用函数绑定语法(::操作符)
"functionBind": false,
// 是否启用 export v from 'mod' 语法
"exportDefaultFrom": false,
// 是否启用 export * as ns from 'mod' 语法
"exportNamespaceFrom": false,
// 是否启用装饰器语法
"decorators": false,
// 是否在导出之前应用装饰器
"decoratorsBeforeExport": false,
// 是否启用顶级 await 语法
"topLevelAwait": false,
// 是否启用 import.meta 语法
"importMeta": false,
// 是否保留所有注释
"preserveAllComments": false
},
// 设置转换插件,通常不需要手动设置
"transform": null,
// 设置目标 JavaScript 版本
// 例如 es3、es5、es2015、es2016、es2017、es2018、es2019、es2020
"target": "es5",
// 是否启用宽松模式,这会使编译后的代码更简短,但可能不完全符合规范
"loose": false,
// 是否引用外部的 helper 函数,而不是内联它们
"externalHelpers": false,
// 是否保留类名,这需要版本 v1.2.50 或更高
// 且 target 需要设置为 es2016 或更高
"keepClassNames": false
},
// 这个配置项用于指示输入的源代码是否是模块代码。
// 如果是,那么 import 和 export 语句将被正常处理
// 否则,它们将被视为语法错误
"isModule": false
}
配置文件
SWC 可通过 .swcrc 文件来明确配置文件,其配置与配置对象一致。
Webpack集成
在 Webpack 工程中,可使用 SWC 搭配 swc-loader 替换 Babel 进行源码转换。
pnpm add @swc/core swc-loader -D
在 Webpack 配置文件中进行配置:
import { resolve } from 'node:path'
/**
* @type {import('webpack').Configuration}
*/
export default {
mode: 'development',
entry: './src/index.js',
output: {
filename: 'main.js',
path: resolve(process.cwd(), './dist')
},
module: {
rules: [
{
test: /\.[jt]sx?$/,
exclude: /node_modules/,
use: {
// 配置 swc-loader
loader: 'swc-loader',
options: {
jsc: {
parser: {
// ecmascript 或 typescript
syntax: 'ecmascript',
// 解析 jsx 语法
jsx: true
},
transform: {
react: {
runtime: 'classic'
}
}
}
}
}
}
]
},
}