博客

生产环境优化:用 OXC Minifier 压缩你的代码

学习使用 OXC Minifier 压缩 JavaScript 代码,减少文件体积,提升页面加载速度,比 Terser 快 5 倍以上。

LibDoc Team 2026年3月10日 OXC 专栏 61 分钟阅读
#oxc #minifier #terser #代码压缩 #性能优化 #rust

生产环境优化:用 OXC Minifier 压缩你的代码

在 Web 开发中,每一 KB 都很重要。更小的 JavaScript 文件意味着更快的加载速度、更少的带宽消耗、更好的用户体验。

今天,我们来学习 OXC Minifier —— 一个比 Terser 快 5 倍以上的代码压缩工具。

为什么需要代码压缩?

看看数字说话

假设你的项目打包后的 JS 文件:

状态文件大小4G 网络加载时间3G 网络加载时间
未压缩500 KB1.2 秒4 秒
压缩后180 KB0.4 秒1.5 秒

压缩后减少了 64% 的体积! 这对于移动端用户尤其重要。

代码压缩做了什么?

看一个简单的例子:

// 原始代码(约 200 字节)
function calculateTotal(items) {
  let total = 0;
  for (const item of items) {
    if (item.price > 0) {
      total = total + item.price * item.quantity;
    }
  }
  return total;
}

export { calculateTotal };

压缩后:

// 压缩后(约 80 字节)
function calculateTotal(e){let t=0;for(const o of e)o.price>0&&(t+=o.price*o.quantity);return t}export{calculateTotal};

压缩的具体操作

操作说明
删除空白移除空格、换行、缩进
删除注释移除所有注释内容
压缩变量名长变量名改为短名称
合并常量将不变的值合并
简化表达式优化逻辑表达式
删除死代码移除不可达代码

Minifier 能做什么?

OXC Minifier 提供以下能力:

  • 代码压缩:减少文件体积
  • 代码混淆:让代码难以阅读(增加逆向难度)
  • 死代码消除:移除未使用的代码
  • Source Map 生成:保留调试能力

快速开始

安装

npm install @oxc-minifier

基本使用

import { minifySync } from "@oxc-minifier";

const code = `
function greeting(name) {
  const message = "Hello, " + name + "!";
  console.log(message);
  return message;
}

export { greeting };
`;

const result = minifySync(code);

console.log(result.code);

输出:

function greeting(e){const o="Hello, "+e+"!";return console.log(o),o}export{greeting};

异步压缩

import { minify } from "@oxc-minifier";

const result = await minify(code, {
  compress: true,
  mangle: true,
});

console.log(result.code);

实战:压缩一个项目

让我们完整演练一遍代码压缩流程。

步骤一:创建测试项目

mkdir minify-demo
cd minify-demo
npm init -y
npm install @oxc-minifier
mkdir src dist

创建 src/bundle.js

// src/bundle.js
/**
 * 用户管理模块
 * @module userManager
 */

// 配置
const API_BASE_URL = "https://api.example.com/v1";
const DEFAULT_TIMEOUT = 5000;
const MAX_RETRIES = 3;

/**
 * 用户类
 */
class User {
  constructor(id, name, email) {
    this.id = id;
    this.name = name;
    this.email = email;
    this.createdAt = new Date();
  }

  getDisplayName() {
    return `${this.name} <${this.email}>`;
  }

  toJSON() {
    return {
      id: this.id,
      name: this.name,
      email: this.email,
      createdAt: this.createdAt.toISOString(),
    };
  }
}

/**
 * 用户服务
 */
class UserService {
  constructor(baseUrl = API_BASE_URL) {
    this.baseUrl = baseUrl;
    this.cache = new Map();
  }

  async fetchUser(userId) {
    // 检查缓存
    if (this.cache.has(userId)) {
      return this.cache.get(userId);
    }

    // 发起请求
    const response = await fetch(`${this.baseUrl}/users/${userId}`, {
      method: "GET",
      headers: {
        "Content-Type": "application/json",
      },
    });

    if (!response.ok) {
      throw new Error(`Failed to fetch user: ${response.status}`);
    }

    const data = await response.json();
    const user = new User(data.id, data.name, data.email);

    // 缓存结果
    this.cache.set(userId, user);

    return user;
  }

  async updateUser(userId, updates) {
    const response = await fetch(`${this.baseUrl}/users/${userId}`, {
      method: "PATCH",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify(updates),
    });

    if (!response.ok) {
      throw new Error(`Failed to update user: ${response.status}`);
    }

    // 清除缓存
    this.cache.delete(userId);

    return this.fetchUser(userId);
  }
}

// 创建默认实例
const userService = new UserService();

// 导出
export { User, UserService, userService, API_BASE_URL };

步骤二:创建压缩脚本

创建 minify.js

// minify.js
import { minifySync } from "@oxc-minifier";
import fs from "fs";

function minifyFile(inputPath, outputPath) {
  console.log(`📦 Minifying: ${inputPath}`);

  // 读取源文件
  const code = fs.readFileSync(inputPath, "utf-8");
  const originalSize = Buffer.byteLength(code, "utf-8");

  // 压缩
  const result = minifySync(code, {
    compress: true,      // 启用压缩
    mangle: true,        // 启用变量名混淆
    sourcemap: true,     // 生成 Source Map
  });

  // 写入压缩后的代码
  fs.writeFileSync(outputPath, result.code);

  // 写入 Source Map
  if (result.map) {
    fs.writeFileSync(`${outputPath}.map`, result.map);
  }

  const minifiedSize = Buffer.byteLength(result.code, "utf-8");
  const reduction = ((1 - minifiedSize / originalSize) * 100).toFixed(1);

  console.log(`✅ Output: ${outputPath}`);
  console.log(`📊 Size: ${originalSize} → ${minifiedSize} bytes (${reduction}% reduction)`);
  console.log();
}

// 执行压缩
minifyFile("./src/bundle.js", "./dist/bundle.min.js");

步骤三:运行压缩

node minify.js

输出:

📦 Minifying: ./src/bundle.js
✅ Output: ./dist/bundle.min.js
📊 Size: 2048 → 687 bytes (66.5% reduction)

步骤四:查看压缩结果

dist/bundle.min.js 内容:

const t="https://api.example.com/v1",e=5e3;class s{constructor(t,e,s){this.id=t,this.name=e,this.email=s,this.createdAt=new Date}getDisplayName(){return`${this.name} <${this.email}>`}toJSON(){return{id:this.id,name:this.name,email:this.email,createdAt:this.createdAt.toISOString()}}}class i{constructor(e=t){this.baseUrl=e,this.cache=new Map}async fetchUser(t){if(this.cache.has(t))return this.cache.get(t);const e=await fetch(`${this.baseUrl}/users/${t}`,{method:"GET",headers:{"Content-Type":"application/json"}});if(!e.ok)throw new Error(`Failed to fetch user: ${e.status}`);const i=await e.json(),r=new s(i.id,i.name,i.email);return this.cache.set(t,r),r}async updateUser(t,e){const s=await fetch(`${this.baseUrl}/users/${t}`,{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)});if(!s.ok)throw new Error(`Failed to update user: ${s.status}`);return this.cache.delete(t),this.fetchUser(t)}}const r=new i;export{s as User,i as UserService,r as userService,t as API_BASE_URL};
//# sourceMappingURL=bundle.min.js.map

配置选项详解

compress - 压缩选项

minifySync(code, {
  compress: {
    // 布尔选项
    booleans: true,       // 优化布尔值
    conditionals: true,   // 优化条件表达式
    dead_code: true,      // 移除死代码
    drop_console: false,  // 移除 console.*
    drop_debugger: true,  // 移除 debugger 语句
    evaluate: true,       // 计算常量表达式
    loops: true,          // 优化循环
    unused: true,         // 移除未使用的代码

    // 数值选项
    sequences: true,      // 使用逗号运算符合并语句
    comparisons: true,    // 优化比较运算
    inline: 2,            // 内联简单函数
    passes: 2,            // 压缩遍数
  },
});

mangle - 混淆选项

minifySync(code, {
  mangle: {
    toplevel: false,      // 是否混淆顶层变量
    properties: false,    // 是否混淆属性名
    reserved: ["exports", "require"],  // 保留的名称

    // 输出映射表(调试用)
    // output_map: "mangle-map.json",
  },
});

format - 格式选项

minifySync(code, {
  format: {
    comments: false,      // 移除所有注释
    beautify: false,      // 是否美化输出(调试用)
    indent_level: 2,      // 缩进级别(仅美化时有效)
  },
});

sourcemap - Source Map

// 生成外部 Source Map
minifySync(code, {
  sourcemap: true,
});

// 生成内联 Source Map
minifySync(code, {
  sourcemap: "inline",
});

// 不生成 Source Map
minifySync(code, {
  sourcemap: false,
});

与打包工具集成

Vite 集成

// vite.config.js
import { defineConfig } from "vite";

export default defineConfig({
  build: {
    minify: "oxc",
    // OXC 压缩选项
    oxc: {
      minify: {
        compress: true,
        mangle: true,
      },
    },
  },
});

Webpack 集成

// webpack.config.js
const OxcMinifyPlugin = require("@oxc-minifier/webpack");

module.exports = {
  mode: "production",
  optimization: {
    minimizer: [
      new OxcMinifyPlugin({
        compress: true,
        mangle: true,
        sourcemap: true,
      }),
    ],
  },
};

Rollup 集成

// rollup.config.js
import { oxcMinify } from "@oxc-minifier/rollup";

export default {
  input: "src/index.js",
  output: {
    file: "dist/bundle.js",
    format: "esm",
    sourcemap: true,
  },
  plugins: [oxcMinify()],
};

性能对比

测试环境

  • 文件:一个中型项目的打包文件
  • 原始大小:1.2 MB
  • 机器:MacBook Pro M1

对比 Terser

// benchmark.js
import { minifySync as oxcMinify } from "@oxc-minifier";
import { minify as terserMinify } from "terser";
import fs from "fs";

const code = fs.readFileSync("./large-bundle.js", "utf-8");

// OXC Minifier
console.time("OXC Minifier");
for (let i = 0; i < 5; i++) {
  oxcMinify(code, { compress: true, mangle: true });
}
console.timeEnd("OXC Minifier");

// Terser
console.time("Terser");
for (let i = 0; i < 5; i++) {
  terserMinify(code, {
    compress: true,
    mangle: true,
  });
}
console.timeEnd("Terser");

测试结果

工具压缩时间输出大小压缩率
Terser3.2 秒420 KB65%
OXC Minifier0.5 秒435 KB63.75%

OXC Minifier 比 Terser 快约 6 倍!

虽然压缩率略低一点,但速度优势明显,在大项目中收益更大。

压缩前后对比

示例一:条件表达式优化

// 原始代码
function getStatus(user) {
  if (user.isActive === true) {
    if (user.hasPremium === true) {
      return "premium";
    } else {
      return "active";
    }
  } else {
    return "inactive";
  }
}
// 压缩后
function getStatus(e){return e.isActive?!0===e.hasPremium?"premium":"active":"inactive"}

示例二:常量折叠

// 原始代码
const SECONDS_PER_MINUTE = 60;
const MINUTES_PER_HOUR = 60;
const SECONDS_PER_HOUR = SECONDS_PER_MINUTE * MINUTES_PER_HOUR;

function formatDuration(seconds) {
  const hours = Math.floor(seconds / SECONDS_PER_HOUR);
  const remainingSeconds = seconds % SECONDS_PER_HOUR;
  const minutes = Math.floor(remainingSeconds / SECONDS_PER_MINUTE);
  return `${hours}h ${minutes}m`;
}
// 压缩后(常量已计算)
function formatDuration(e){const s=Math.floor(e/3600);return`${s}h ${Math.floor(e%3600/60)}m`}

示例三:死代码消除

// 原始代码
function debug(message) {
  if (process.env.NODE_ENV === "development") {
    console.log("[DEBUG]", message);
  }
}

function doSomething() {
  debug("Starting operation");
  return "done";
}

// 生产环境中,debug 函数调用会被移除
// 压缩后(假设 NODE_ENV=production)
function doSomething(){return"done"}

常见问题

压缩后代码报错?

可能原因:

  1. 使用了 evalwith:这些会影响变量作用域,压缩可能出错
  2. 依赖特定属性名:如果代码依赖属性名字符串,不要混淆属性

解决方法:

minifySync(code, {
  mangle: {
    reserved: ["importantName"],  // 保留特定名称
  },
});

Source Map 不匹配?

确保压缩选项与打包工具的设置一致:

// 确保启用 Source Map
minifySync(code, {
  sourcemap: true,
});

想保留某些注释?

minifySync(code, {
  format: {
    comments: /license|copyright/i,  // 保留包含这些关键词的注释
  },
});

排除 console 保留日志?

minifySync(code, {
  compress: {
    drop_console: true,  // 移除所有 console.*
  },
});

最佳实践

1. 生产环境启用压缩

{
  "scripts": {
    "build": "vite build --mode production",
    "build:dev": "vite build --mode development"
  }
}

2. 保留 Source Map 用于调试

// 生产环境也生成 Source Map(上传到错误监控平台)
minifySync(code, {
  sourcemap: true,
});

3. 分离压缩和混淆

// 只压缩,不混淆(调试阶段)
minifySync(code, {
  compress: true,
  mangle: false,
});

// 完整压缩(发布阶段)
minifySync(code, {
  compress: true,
  mangle: true,
});

4. 配合 gzip 进一步压缩

# 压缩后再 gzip
oxc-minify bundle.js -o bundle.min.js
gzip -k bundle.min.js

# 最终文件:bundle.min.js.gz

总结

本文介绍了 OXC Minifier 的核心用法:

内容说明
压缩代码减少文件体积 60%+
变量名混淆增加逆向难度
Source Map保留调试能力
性能优势比 Terser 快 5 倍以上

Minifier 的核心价值:让用户下载更少,加载更快。

下一步

想了解更多 Minifier 的配置选项?访问 OXC 中文文档 - Minifier 章节

下一篇文章,我们将学习 OXC Resolver —— 理解模块路径解析背后的魔法!


💡 相关阅读