Skip to content

Удаление мёртвого кода

Минификатор Oxc поддерживает удаление мёртвого кода. Например, удаляются операторы внутри блока if (false) и неиспользуемые приватные поля класса.

Эта возможность всегда включена; удалять больше кода можно, включив отдельные опции.

Полезные возможности трансформера

Помимо опций ниже можно использовать возможность define в трансформере, чтобы подставлять глобальные идентификаторы константными выражениями и удалять ещё больше мёртвого кода.

Drop Console

Удалить все вызовы console.* можно опцией dropConsole. Ведёт себя аналогично опции drop_console в Terser и drop: ['console'] в esbuild.

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

// output
const bar = window.bar();
js
// Example
import { minify } from "oxc-minify";

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

Удаляется всё выражение вызова

Эта опция убирает всё выражение вызова, включая аргументы. Так задумано: не вычислять аргументы вызова полезно для производительности, если они дорогие. Но если у аргументов есть побочные эффекты, поведение кода изменится. Чтобы сохранить вычисление аргументов, можно использовать опцию compress.treeshake.manualPureFunctions: ['console'].

Drop Debugger

Удалить все операторы debugger можно опцией dropDebugger. По умолчанию она включена. Поведение близко к drop_debugger в Terser и drop: ['debugger'] в esbuild.

js
// input
debugger;

// output
js
// Example
import { minify } from "oxc-minify";

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

Drop Labels

Удалить все помеченные операторы с указанными метками можно опцией dropLabels. Поведение близко к dropLabels в esbuild.

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

// output
console.log("bar");
js
// Example
import { minify } from "oxc-minify";

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

Неиспользуемые объявления

Все неиспользуемые объявления функций / классов / переменных удаляются по умолчанию. Сохранить их можно опцией unused.

js
// input
{
  function foo() {}
}

// output
js
// Example
import { minify } from "oxc-minify";

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

Сохранение значений свойства name

По умолчанию минификатор Oxc считает, что код не опирается на свойство name у функций и классов: name выводится из имени функции/класса или переменной, а сохранение исходного имени мешает уменьшению размера вывода.

Чтобы сохранять значения name, используйте опцию keepNames.

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

// output
var bar = function foo() {};
js
// Example
import { minify } from "oxc-minify";

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

Опция mangle.keepNames

При использовании манглинга имеет смысл также включить опцию mangle.keepNames.

Управление определением побочных эффектов

Есть несколько опций, управляющих тем, как определяются побочные эффекты.

Аннотации pure

По умолчанию минификатор Oxc учитывает аннотации pure. Это комментарии, помечающие выражения, которые безопасно удалять, если их результат не используется. Подробнее см. черновик спецификации.

Отключить можно опцией compress.treeshake.annotations: false.

#__PURE__ / @__PURE__

Аннотация #__PURE__ помечает вызовы функций, которые можно безопасно убрать, если результат не используется. Помечается только сам вызов, аргументы не входят в пометку.

Чтобы пометить другие выражения или включить аргументы, оберните их в IIFE и поставьте #__PURE__ на неё.

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

// output
bar();
console.log(foo());
console.log(new Foo());

Функция не обязана быть «чистой»

Несмотря на название, функция не обязана быть чистой (Pure function — Wikipedia). Это не означает, что вызовы можно кэшировать; функция не обязана быть референциально прозрачной (Referential transparency — Wikipedia).

#__NO_SIDE_EFFECTS__ / @__NO_SIDE_EFFECTS__

Аннотация #__NO_SIDE_EFFECTS__ помечает объявление функции так, что все её вызовы можно безопасно удалить, если результат не используется. Удобно, если такая функция вызывается в нескольких местах.

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

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

Определение чистых функций

Вместо аннотаций можно перечислить имена функций в compress.treeshake.manualPureFunctions. Похоже на treeshake.manualPureFunctions в Rollup и опцию pure_funcs в Terser.

js
// input
foo();
foo.bar();
bar();
bar.baz();
new foo();
foo``;

// output
bar();
js
// Example
import { minify } from "oxc-minify";

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

Игнорирование побочных эффектов чтения свойств

По умолчанию минификатор считает, что чтение свойства может иметь побочные эффекты: обращение к свойству null бросает ошибку; свойство может быть геттером с эффектом. Можно указать игнорировать это через compress.treeshake.propertyReadSideEffects: false. Похоже на treeshake.propertyReadSideEffects в Rollup и pure_getters в Terser.

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

// output (with `compress.treeshake.propertyReadSideEffects: false`)

Игнорирование побочных эффектов доступа к глобальным переменным

По умолчанию доступ к глобальным переменным считается имеющим побочные эффекты: обращение к несуществующей глобальной переменной бросает ошибку; глобаль может быть геттером. Игнорировать это можно compress.treeshake.unknownGlobalSideEffects: false. Похоже на treeshake.unknownGlobalSideEffects в Rollup.

js
// input
const jQuery = $;

// output (with `compress.treeshake.propertyReadSideEffects: false`)

Игнорирование побочных эффектов некорректных import

По умолчанию считается, что у операторов import нет побочных эффектов. Они появляются, если:

  • модуль импорта не удаётся разрешить;
  • имя импорта не экспортируется из модуля.

Чтобы сохранять такие эффекты, установите compress.treeshake.invalidImportSideEffects: true.

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

// output (with `compress.treeshake.invalidImportSideEffects: true`)
import { existing } from "cannot-be-resolved";
import { missing } from "somewhere";

// output (with `compress.treeshake.invalidImportSideEffects: false`)