深入 SWC 编译器构建选项(压缩、混淆)
NestJS 默认支持两种编译器:TSC(TypeScript Compiler)和 SWC(Speedy Web Compiler)。SWC 基于 Rust 编写,编译速度远快于 TSC。本节深入探讨 SWC 的配置选项,包括代码压缩(minify)、混淆(mangle)以及其他关键编译参数。
TSC vs SWC 对比
| 特性 | TSC | SWC |
|---|---|---|
| 语言 | TypeScript | Rust |
| 类型检查 | 默认开启 | 默认关闭(需手动开启 --typeCheck) |
| 编译速度 | 较慢 | 极快(约 20-70x 提速) |
| 代码压缩 | 不支持 | 内置支持 |
| 代码混淆 | 不支持 | 内置支持 |
| 输出格式 | 保持源码结构 | 保持源码结构 |
TSC 默认开启类型校验,如果 Controller 中有未完成的 Service 代码会直接报错。SWC 默认不校验类型,如需开启可在
nest-cli.json中添加--typeCheck参数。
SWC 配置文件结构
SWC 使用 .swcrc 作为配置文件,支持 JSON 格式。官方推荐使用 schema 文件获得 IDE 补全:
{
"$schema": "https://swc.rs/schema.json"
}
json
完整配置示例
{
"$schema": "https://swc.rs/schema.json",
"sourceMaps": true,
"minify": false,
"jsc": {
"parser": {
"syntax": "typescript",
"decorators": true,
"dynamicImport": true
},
"transform": {
"legacyDecorator": true,
"decoratorMetadata": true
},
"target": "es2020",
"minify": {
"compress": {
"unused": true,
"drop_console": true,
"drop_debugger": true,
"dead_code": true,
"evaluate": true,
"conditionals": true,
"collapse_vars": true,
"reduce_vars": true,
"join_vars": true,
"if_return": true,
"sequences": true,
"passes": 2
},
"mangle": true
}
},
"module": {
"type": "commonjs"
}
}
json
代码压缩(Minify)
从 SWC 1.2.67 版本开始,可以直接在配置中启用 minify:
{
"minify": true
}
json
开启后,编译输出的代码会被压缩为单行。但仅开启 minify 的效果有限 -- 通过格式化工具仍然可以还原代码的可读性。
compress 选项详解
jsc.minify.compress 提供了丰富的压缩选项,与 Terser 插件的配置方式类似:
| 选项 | 说明 | 推荐值 |
|---|---|---|
drop_console | 移除所有 console.* 调用 | true(生产环境) |
drop_debugger | 移除 debugger 语句 | true |
dead_code | 移除不可达的死代码 | true |
unused | 移除未使用的变量和函数 | true |
evaluate | 预计算常量表达式 | true |
conditionals | 优化条件判断语句 | true |
collapse_vars | 折叠变量声明 | true |
reduce_vars | 优化变量使用 | true |
join_vars | 合并变量声明 | true |
if_return | 优化 if-return 模式 | true |
sequences | 使用逗号表达式合并语句 | true |
passes | 压缩遍数 | 2 |
代码混淆(Mangle)
混淆的核心目的是增加代码的不可读性,使反编译后的代码难以理解。开启 mangle 后,变量名、函数名会被替换为单字母标识符:
{
"jsc": {
"minify": {
"mangle": true
}
}
}
json
mangle 高级选项
{
"jsc": {
"minify": {
"mangle": {
"topLevel": true,
"keepClassNames": false,
"keepFnNames": false
}
}
}
}
json
| 选项 | 说明 |
|---|---|
topLevel | 是否混淆顶层作用域的变量名 |
keepClassNames | 是否保留类名 |
keepFnNames | 是否保留函数名 |
保留特定名称
如果需要保留某些特定的标识符不被混淆(如对外暴露的 API 名称),可以使用 reserved 配置:
{
"jsc": {
"minify": {
"mangle": {
"reserved": ["AppController", "AppService"]
}
}
}
}
json
压缩混淆效果对比
// 原始代码
class AppController {
private readonly appService: AppService;
constructor(appService: AppService) {
this.appService = appService;
}
@Get()
getHello(): string {
return this.appService.getHello();
}
}
// 仅压缩(minify: true)
class AppController{constructor(t){this.appService=t}getHello(){return this.appService.getHello()}}
// 压缩 + 混淆(minify + mangle)
class c{constructor(r){this.s=r}t(){return this.s.t()}}
text
没有 .map 文件的情况下,混淆后的代码几乎无法还原到原始逻辑。
Parser 配置选项
{
"jsc": {
"parser": {
"syntax": "typescript",
"tsx": false,
"decorators": true,
"dynamicImport": true
},
"transform": {
"legacyDecorator": true,
"decoratorMetadata": true
},
"keepClassNames": true
}
}
json
| 选项 | 说明 | 推荐值 |
|---|---|---|
syntax | 语法类型 | "typescript" |
tsx | 是否支持 JSX 解析 | false(服务端项目) |
decorators | 是否支持装饰器语法 | true(NestJS 必需) |
dynamicImport | 是否支持 import() 动态导入 | true |
legacyDecorator | 使用旧版装饰器语法 | true |
decoratorMetadata | 启用装饰器元数据 | true(NestJS 必需) |
keepClassNames | 保留类名 | true |
SWC 的局限性
SWC 是一个编译器(compiler),不是打包器(bundler)。它只做语法转换,不会:
- 将
node_modules中的依赖打包进输出目录 - 将多个文件合并为单文件
- 处理
require/import的模块解析
如果需要完整的打包功能,需要配合 webpack 或 Rollup 使用。
SWC Pack(实验性)
SWC 官方正在开发 @swc/pack(前身是 spack),目标是提供类似 webpack 的打包能力。目前仍处于开发阶段,不建议在生产环境使用。
升级 SWC Core
建议定期升级 @swc/core 以获取最新的配置选项和 bug 修复:
# 检查可用更新
npx ncu -u
# 或直接更新到指定版本
pnpm add -D @swc/core@1.5.25
bash
小结
本节深入讲解了 SWC 编译器的配置体系,核心要点:
- minify:开启代码压缩,配合
compress选项精细控制压缩策略 - mangle:开启代码混淆,增加反编译难度,支持保留指定名称
- parser:配置 TypeScript 装饰器、动态导入等语法支持
- 局限性:SWC 仅做语法转换,打包需配合 webpack/Rollup
- 版本管理:及时更新 patch 和 minor 版本,major 版本需谨慎
下一节将介绍如何将 webpack 配合 SWC loader 实现完整的 NestJS 项目打包。
↑