Skip to content

死代码消除

Oxc 压缩器支持消除死代码。例如,它会移除 if (false) 块内的语句以及未使用的私有类字段。

此功能始终启用,但通过启用某些选项可以进一步移除更多代码。

变换器中的有用特性

除了以下选项外,您还可以使用 变换器中的 define 功能 将全局标识符替换为常量表达式,以进一步消除死代码。

移除 console 调用

通过启用 dropConsole 选项,您可以移除所有 console.* 调用。此选项的行为类似于 Terserdrop_console 选项以及 esbuild 的 drop: ['console'] 选项

js
// 输入
const bar = window.bar();
console.log("foo", bar, baz());

// 输出
const bar = window.bar();
js
// 示例
import { minify } from "oxc-minify";

const result = await minify("lib.js", code, {
  compress: {
    dropConsole: true,
  },
});

整个调用表达式都会被移除

请注意,此选项会移除整个调用表达式(包括参数)。这是有意为之的,因为如果这些参数计算代价高昂,则移除其求值有助于提升运行时性能。然而,如果这些参数中存在副作用,此转换将改变代码的行为。如果您希望保留参数,可以使用 compress.treeshake.manualPureFunctions: ['console'] 选项。

移除 debugger 语句

通过启用 dropDebugger 选项,您可以移除所有 debugger 语句。此选项默认启用。其行为类似于 Terserdrop_debugger 选项以及 esbuild 的 drop: ['debugger'] 选项

js
// 输入
debugger;

// 输出
js
// 示例
import { minify } from "oxc-minify";

const result = await minify("lib.js", code, {
  compress: {
    dropDebugger: true,
  },
});

移除标签语句

通过启用 dropLabels 选项,您可以移除具有指定标签的所有标签语句。此选项的行为类似于 esbuild 的 dropLabels 选项

js
// 输入
DEV: console.log("foo");
console.log("bar");

// 输出
console.log("bar");
js
// 示例
import { minify } from "oxc-minify";

const result = await minify("lib.js", code, {
  compress: {
    dropLabels: ["DEV"],
  },
});

未使用的声明

所有未使用的函数 / 类 / 变量声明默认都会被移除。您可以通过使用 unused 选项来保留它们。

js
// 输入
{
  function foo() {}
}

// 输出
js
// 示例
import { minify } from "oxc-minify";

const result = await minify("lib.js", code, {
  compress: {
    unused: true, // 或 "keep_assign"
  },
});

保留 name 属性值

默认情况下,Oxc 压缩器假设您的代码不依赖于函数或类的 name 属性。这是因为 name 属性是从函数或类名称或变量名称推断而来的,保留原始名称会阻碍输出体积的减小。

若要保留 name 属性值,可以使用 keepNames 选项。

js
// 输入
var bar = function foo() {};

// 输出
var bar = function foo() {};
js
// 示例
import { minify } from "oxc-minify";

const result = await minify("lib.js", code, {
  compress: {
    keepNames: true, // 等价于 { function: true, class: true }
  },
});

mangle.keepNames 选项

如果您正在使用命名混淆功能,还可能需要启用 mangle.keepNames 选项

控制副作用检测

有多个选项可用于控制副作用检测。

纯函数注释

默认情况下,Oxc 压缩器会尊重纯函数注释。纯函数注释是标记表达式的一种注释,表示只要其返回值未被使用,这些表达式就可以安全地被移除。更多信息请参见 草案规范提案

您可以通过将 compress.treeshake.annotations 选项设置为 false 来禁用此功能。

#__PURE__ / @__PURE__

#__PURE__ 注释用于标记那些在返回值未被使用时可安全移除的函数调用。请注意,它仅标记函数调用本身,并不涵盖其参数。

如果您希望标记其他表达式或覆盖参数,可以将它们包装在 IIFE(立即执行函数表达式)中,并将 #__PURE__ 注释放在该 IIFE 上。

js
// 输入
/* #__PURE__ */ foo();
/* #__PURE__ */ new Foo();
/* #__PURE__ */ foo(bar());
/* #__PURE__ */ (() => {
  foo(bar());
})();
console.log(/* #__PURE__ */ foo());
console.log(/* #__PURE__ */ new Foo());

// 输出
bar();
console.log(foo());
console.log(new Foo());

函数不必是纯函数

尽管名为“纯”,但该函数并不需要是真正的纯函数 (纯函数 - 维基百科)。它并不表示调用可以被缓存。换句话说,该函数不需要具有引用透明性 (引用透明性 - 维基百科)。

#__NO_SIDE_EFFECTS__ / @__NO_SIDE_EFFECTS__

#__NO_SIDE_EFFECTS__ 注释用于标记一个函数声明,表示只要其返回值未被使用,所有对该函数的调用都可以安全地被移除。当您在多个位置调用同一个函数时,这非常有用。

js
// 输入
/* #__NO_SIDE_EFFECTS__ */
export function foo() {}
/* #__NO_SIDE_EFFECTS__ */
export const bar = () => {};
foo();
bar();

// 输出
export function foo() {}
export const bar = () => {};

定义纯函数

除了使用纯函数注释标记函数外,您还可以通过 compress.treeshake.manualPureFunctions 选项来标记函数。该选项是一个函数名数组。此功能类似于 Rollup 的 treeshake.manualPureFunctions 选项Terserpure_funcs 选项。

js
// 输入
foo();
foo.bar();
bar();
bar.baz();
new foo();
foo``;

// 输出
bar();
js
// 示例
import { minify } from "oxc-minify";

const result = await minify("lib.js", code, {
  compress: {
    treeshake: {
      manualPureFunctions: ["foo", "bar.baz"],
    },
  },
});

忽略属性读取的副作用

默认情况下,Oxc 压缩器假设属性读取具有副作用。这是因为访问 null 的属性会抛出错误。此外,也存在属性是获取器(getter)的情况,而获取器可能具有副作用。您可以通过将 compress.treeshake.propertyReadSideEffects 选项设置为 false 来告诉 Oxc 压缩器忽略这些可能性。此功能类似于 Rollup 的 treeshake.propertyReadSideEffects 选项Terserpure_getters 选项。

js
// 输入
const foo = {
  get bar() {
    console.log("effect");
    return "bar";
  },
};
foo.bar;

// 输出(当 `compress.treeshake.propertyReadSideEffects: false` 时)

忽略全局变量访问的副作用

默认情况下,Oxc 压缩器假设全局变量访问具有副作用。这是因为访问不存在的全局变量会抛出错误。此外,也存在全局变量是获取器(getter)的情况,而获取器可能具有副作用。您可以通过将 compress.treeshake.unknownGlobalSideEffects 选项设置为 false 来告诉 Oxc 压缩器忽略这些可能性。此功能类似于 Rollup 的 treeshake.unknownGlobalSideEffects 选项

js
// 输入
const jQuery = $;

// 输出(当 `compress.treeshake.propertyReadSideEffects: false` 时)

忽略无效导入语句的副作用

默认情况下,Oxc 压缩器假设导入语句没有副作用。但在以下情况下,导入语句确实具有副作用:

  • 导入无法解析
  • 导入名称在被导入模块中未被导出

如果需要保留这些副作用,您可以通过将 compress.treeshake.invalidImportSideEffects 选项设置为 true 来指示 Oxc 压缩器保留它们。

js
// 输入
import { existing } from "cannot-be-resolved";
import { missing } from "somewhere";

// 输出(当 `compress.treeshake.invalidImportSideEffects: true` 时)
import { existing } from "cannot-be-resolved";
import { missing } from "somewhere";

// 输出(当 `compress.treeshake.invalidImportSideEffects: false` 时)