死代码消除
Oxc 压缩器支持消除死代码。例如,它会移除 if (false) 块内的语句以及未使用的私有类字段。
此功能始终启用,但通过启用某些选项可以进一步移除更多代码。
变换器中的有用特性
除了以下选项外,您还可以使用 变换器中的 define 功能 将全局标识符替换为常量表达式,以进一步消除死代码。
移除 console 调用
通过启用 dropConsole 选项,您可以移除所有 console.* 调用。此选项的行为类似于 Terser 的 drop_console 选项以及 esbuild 的 drop: ['console'] 选项。
// 输入
const bar = window.bar();
console.log("foo", bar, baz());
// 输出
const bar = window.bar();// 示例
import { minify } from "oxc-minify";
const result = await minify("lib.js", code, {
compress: {
dropConsole: true,
},
});整个调用表达式都会被移除
请注意,此选项会移除整个调用表达式(包括参数)。这是有意为之的,因为如果这些参数计算代价高昂,则移除其求值有助于提升运行时性能。然而,如果这些参数中存在副作用,此转换将改变代码的行为。如果您希望保留参数,可以使用 compress.treeshake.manualPureFunctions: ['console'] 选项。
移除 debugger 语句
通过启用 dropDebugger 选项,您可以移除所有 debugger 语句。此选项默认启用。其行为类似于 Terser 的 drop_debugger 选项以及 esbuild 的 drop: ['debugger'] 选项。
// 输入
debugger;
// 输出// 示例
import { minify } from "oxc-minify";
const result = await minify("lib.js", code, {
compress: {
dropDebugger: true,
},
});移除标签语句
通过启用 dropLabels 选项,您可以移除具有指定标签的所有标签语句。此选项的行为类似于 esbuild 的 dropLabels 选项。
// 输入
DEV: console.log("foo");
console.log("bar");
// 输出
console.log("bar");// 示例
import { minify } from "oxc-minify";
const result = await minify("lib.js", code, {
compress: {
dropLabels: ["DEV"],
},
});未使用的声明
所有未使用的函数 / 类 / 变量声明默认都会被移除。您可以通过使用 unused 选项来保留它们。
// 输入
{
function foo() {}
}
// 输出// 示例
import { minify } from "oxc-minify";
const result = await minify("lib.js", code, {
compress: {
unused: true, // 或 "keep_assign"
},
});保留 name 属性值
默认情况下,Oxc 压缩器假设您的代码不依赖于函数或类的 name 属性。这是因为 name 属性是从函数或类名称或变量名称推断而来的,保留原始名称会阻碍输出体积的减小。
若要保留 name 属性值,可以使用 keepNames 选项。
// 输入
var bar = function foo() {};
// 输出
var bar = function foo() {};// 示例
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 上。
// 输入
/* #__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__ 注释用于标记一个函数声明,表示只要其返回值未被使用,所有对该函数的调用都可以安全地被移除。当您在多个位置调用同一个函数时,这非常有用。
// 输入
/* #__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 选项 和 Terser 的 pure_funcs 选项。
// 输入
foo();
foo.bar();
bar();
bar.baz();
new foo();
foo``;
// 输出
bar();// 示例
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 选项 和 Terser 的 pure_getters 选项。
// 输入
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 选项。
// 输入
const jQuery = $;
// 输出(当 `compress.treeshake.propertyReadSideEffects: false` 时)忽略无效导入语句的副作用
默认情况下,Oxc 压缩器假设导入语句没有副作用。但在以下情况下,导入语句确实具有副作用:
- 导入无法解析
- 导入名称在被导入模块中未被导出
如果需要保留这些副作用,您可以通过将 compress.treeshake.invalidImportSideEffects 选项设置为 true 来指示 Oxc 压缩器保留它们。
// 输入
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` 时)