Удаление мёртвого кода (Dead Code Elimination, DCE) в SWC представляет собой набор компиляционных оптимизаций, направленных на исключение из итогового бандла функций, переменных, выражений и модулей, которые не используются в программе и не оказывают влияния на её поведение.
Под «мёртвым кодом» в контексте JavaScript подразумеваются:
Основная сложность заключается в том, что JavaScript допускает побочные эффекты при загрузке и выполнении кода, поэтому удаление требует строгого анализа контекста.
В SWC удаление мёртвого кода выполняется на этапе минификации и включает несколько взаимосвязанных проходов:
Ключевая особенность заключается в том, что оптимизация выполняется не только на уровне отдельных выражений, но и на уровне модулей, что позволяет устранять целые фрагменты кода при отсутствии внешних ссылок.
Удаление мёртвого кода невозможно без анализа графа зависимостей. В SWC этот процесс строится вокруг следующих шагов:
Особое значение имеет различие между:
import() и реэкспорты);
Если модуль не имеет побочных эффектов и его экспорт не используется, он может быть полностью исключён.
Наиболее эффективное удаление мёртвого кода в SWC достигается при
использовании ES Modules (import / export),
поскольку их статическая структура позволяет анализировать зависимости
на этапе компиляции.
Пример:
export function used() {
return 1;
}
export function unused() {
return 2;
}
Если импортируется только used, функция unused
удаляется на этапе минификации.
Ключевые факторы:
При использовании CommonJS (require,
module.exports) эффективность удаления мёртвого кода в SWC
значительно снижается.
Причины:
require() может вызываться динамически;
module.exports может изменяться в рантайме;
Пример проблемного паттерна:
const lib = require("./lib");
if (false) {
lib.heavyFunction();
}
Хотя условие явно ложное, статический анализ не всегда может безопасно удалить код без риска изменения поведения.
Удаление мёртвого кода в SWC строго зависит от анализа побочных эффектов (side effects).
Модуль считается «чистым», если:
Пример побочного эффекта:
console.log("module loaded");
export const value = 42;
Такой модуль не может быть полностью удалён даже при отсутствии
использования value.
Для управления поведением используются:
В SWC важную роль играет поддержка аннотаций, позволяющих явно указать отсутствие побочных эффектов.
Наиболее распространённый механизм:
/*#__PURE__*/ createInstance();
Это позволяет минификатору:
Пример:
const x = /*#__PURE__*/ factory();
Если x не используется, вызов factory()
удаляется полностью.
Конфигурация оптимизаций в SWC осуществляется через
minify-параметры:
{
jsc: {
minify: {
compress: {
unused: true,
dead_code: true
},
mangle: true
}
}
}
Ключевые параметры:
compress.unused — удаление неиспользуемых переменных и
функций;
compress.dead_code — устранение недостижимых блоков;
mangle — сокращение имён идентификаторов после анализа
использования.
Дополнительно учитываются:
Удаление мёртвого кода тесно связано с другими оптимизациями в SWC:
Пример:
function add(a, b) {
return a + b;
}
const result = add(2, 3);
После оптимизации:
const result = 5;
Если result не используется, весь фрагмент удаляется.
Удаление мёртвого кода в SWC часто работает совместно с tree shaking на уровне сборщика.
Разделение ответственности:
Эффективность максимальна при соблюдении условий:
“sideEffects”: false в package.json.
Поведение DCE в SWC зависит от структуры кода.
Неоптимальный пример:
function debug() {
console.log("debug");
}
debug();
Если функция вызывается только в условии, которое всегда ложное, оптимизатор может удалить вызов, но не всегда саму функцию при сложных зависимостях.
Оптимизированный вариант:
/*#__PURE__*/ (() => {
console.log("debug");
})();
При отсутствии использования результата весь блок может быть удалён.
Мёртвый код часто возникает внутри условных выражений:
if (process.env.NODE_ENV === "production") {
console.log("dev only");
}
В SWC такие конструкции могут быть устранены при известном значении переменной окружения на этапе сборки.
После подстановки:
if (false) {
console.log("dev only");
}
Далее блок полностью удаляется как недостижимый.
Удаление мёртвого кода распространяется и на свойства объектов:
const config = {
a: 1,
b: 2,
c: 3
};
console.log(config.a);
После анализа использования:
const config = {
a: 1
};
Остальные свойства исключаются, если отсутствуют побочные эффекты и динамическое обращение.
В SWC сложность резко возрастает при использовании:
eval;
with;
obj[key] с неизвестным
key).
В таких случаях оптимизатор вынужден сохранять код, поскольку статический анализ не гарантирует корректность удаления.
const key = getKey();
obj[key] = 10;
Удаление свойств становится невозможным без потери семантики.