Сжатие литералов и выражений

Общие принципы оптимизации литералов

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

Ключевая цель данного этапа — уменьшение объёма кода за счёт:

  • вычисления константных выражений;
  • упрощения логических конструкций;
  • удаления избыточных операций над неизменяемыми значениями;
  • свёртки строк и чисел;
  • устранения неиспользуемых ветвей.

Свёртка константных выражений

Одним из базовых механизмов является constant folding — вычисление выражений, результат которых известен заранее.

Примеры преобразований:

const a = 2 + 3;

преобразуется в:

const a = 5;

Аналогично для более сложных случаев:

const b = 10 * (2 + 3);

становится:

const b = 50;

Такая оптимизация применяется не только к числам, но и к строкам:

const msg = "Hello, " + "world";

результат:

const msg = "Hello, world";

Оптимизация строковых литералов

При сжатии строк выполняется несколько уровней преобразований:

  • конкатенация строковых литералов;
  • удаление лишних escape-последовательностей;
  • выбор наиболее короткого представления строки;
  • сведение выражений вида "a" + "b" + "c" к "abc".

Пример:

const path = "api/" + "v1/" + "users";

становится:

const path = "api/v1/users";

Дополнительно могут применяться преобразования Unicode-escape последовательностей в более компактный вид, если это не влияет на интерпретацию строки.


Свёртка логических выражений

Логические операции являются одним из ключевых объектов оптимизации. При известном значении операндов выражения упрощаются до констант.

Примеры:

const a = true && false;

упрощается до:

const a = false;
const b = false || "value";

становится:

const b = "value";

Особое внимание уделяется трёхчастным выражениям:

const c = true ? 1 : 2;

результат:

const c = 1;

Упрощение тернарных операторов

Тернарные выражения подвергаются глубокой оптимизации при наличии константных условий.

Пример:

const mode = "prod";
const isProd = mode === "prod" ? true : false;

преобразуется в:

const isProd = true;

Если ветви тернарного оператора содержат одинаковые значения, выражение полностью схлопывается:

const x = condition ? 10 : 10;

результат:

const x = 10;

Удаление мёртвых ветвей кода

При анализе условий с известным результатом происходит устранение недостижимых блоков.

if (false) {
  doSomething();
}

полностью удаляется.

При более сложных условиях:

if (1 > 2) {
  foo();
} else {
  bar();
}

сохраняется только:

bar();

Такое поведение критически важно для уменьшения итогового размера бандла, особенно в условиях feature-flag логики.


Свёртка числовых выражений

Числовые операции оптимизируются с учётом приоритетов операторов и ассоциативности.

const x = 100 / 2 * 3;

преобразуется в:

const x = 150;

Также учитываются побочные свойства операций:

  • сложение с нулём устраняется;
  • умножение на 1 удаляется;
  • умножение на 0 сворачивается в 0.

Примеры:

const a = n + 0;

const a = n;
const b = n * 1;

const b = n;
const c = n * 0;

const c = 0;

Инлайнинг констант и выражений

Если значение переменной известно на этапе сборки и не изменяется, оно может быть встроено непосредственно в места использования.

const SIZE = 1024;
const area = SIZE * 2;

становится:

const area = 1024 * 2;

а затем дополнительно:

const area = 2048;

Подобная цепочка оптимизаций формирует эффект каскадного упрощения.


Устранение избыточных преобразований типов

В выражениях, где преобразование типов не влияет на результат, оно удаляется.

const a = !!true;

const a = true;
const b = Number("42");

const b = 42;

если строковый литерал является статическим и корректно парсится как число.


Упрощение цепочек операций

Многоуровневые выражения разбираются на составные части и приводятся к минимальной форме.

const x = (((2 + 3) * 4) - 0);

преобразуется последовательно:

const x = (5 * 4);
const x = 20;

Свёртка выражений с побочными эффектами

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

"debug" && console.log("test");

остаётся без изменений, так как console.log имеет побочный эффект.

Однако:

"debug" && 42;

упрощается до:

42;

или может быть удалено целиком, если результат не используется.


Оптимизация побитовых и арифметических выражений

Побитовые операции также подвергаются свёртке:

const mask = 0xff & 0xff;

const mask = 255;

Аналогично:

const flag = 1 << 3;

const flag = 8;

Влияние режима минификации

Поведение сжатия литералов и выражений зависит от включённых режимов:

  • minify — включает полный набор оптимизаций;
  • minifySyntax — отвечает за синтаксические упрощения;
  • minifyWhitespace — удаляет пробельные символы без изменения структуры;
  • minifyIdentifiers — сокращает имена переменных, не влияя на литералы, но усиливая общий эффект сжатия.

Комбинация этих режимов усиливает результат, однако именно оптимизация литералов и выражений даёт наиболее заметное уменьшение размера за счёт устранения избыточной вычислительной структуры.