Настройки Terser: mangle, compress, comments

Terser используется в Webpack для минимизации JavaScript-кода и является стандартным инструментом в production-сборках. Его основная задача — уменьшение размера бандла за счёт удаления лишнего кода, сокращения идентификаторов и оптимизации выражений без изменения поведения программы.

В Webpack интеграция осуществляется через TerserPlugin, который является обёрткой над библиотекой Terser и предоставляет доступ к ключевым настройкам: mangle, compress, format.comments.


Базовая настройка в Webpack выглядит следующим образом:

const TerserPlugin = require("terser-webpack-plugin");

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        terserOptions: {
          mangle: {},
          compress: {},
          format: {
            comments: false
          }
        }
      })
    ]
  }
};

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


mangle: переименование идентификаторов

Назначение

Параметр mangle отвечает за сокращение имён переменных, функций, классов и свойств объекта. Это один из ключевых механизмов уменьшения размера итогового JavaScript-файла.

Исходный код:

function calculateTotalPrice(userCart) {
  const totalPrice = userCart.reduce((sum, item) => sum + item.price, 0);
  return totalPrice;
}

После mangle:

function a(b){return b.reduce((a,b)=>a+b.price,0)}

Базовая конфигурация

mangle: true

или более явно:

mangle: {
  toplevel: false,
  keep_fnames: false,
  keep_classnames: false
}

toplevel

mangle.toplevel включает переименование переменных и функций в глобальной области видимости.

mangle: {
  toplevel: true
}

Эффект:

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

Используется в максимально агрессивных production-сборках.


keep_fnames

mangle: {
  keep_fnames: true
}

Отключает переименование имён функций.

Применяется в случаях:

  • dependency injection (например, AngularJS старого типа)
  • логирование через Function.name
  • сериализация функций

keep_classnames

mangle: {
  keep_classnames: true
}

Сохраняет имена классов без изменения.

Важные сценарии:

  • ORM, завязанные на constructor.name
  • рефлексия
  • DI контейнеры

safari10 и IE-особенности

mangle: {
  safari10: true
}

Используется для обхода багов старых JS-движков, где агрессивный mangle может ломать поведение let/const или destructuring.


reserved

Позволяет исключить идентификаторы из минификации:

mangle: {
  reserved: ["React", "Vue", "MyGlobal"]
}

Типичный сценарий — работа с глобальными библиотеками, где имя должно остаться неизменным.


compress: оптимизация AST

Назначение

compress выполняет анализ и преобразование дерева синтаксиса (AST), удаляя лишние конструкции и упрощая выражения.

Это наиболее сложный и мощный этап минификации.


Базовая конфигурация

compress: {
  dead_code: true,
  drop_console: false,
  drop_debugger: true
}

Основные опции compress


dead_code

Удаление недостижимого кода:

compress: {
  dead_code: true
}

Пример:

if (false) {
  console.log("never executed");
}

После оптимизации блок полностью удаляется.


drop_console

Удаление console.*:

compress: {
  drop_console: true
}

Пример:

console.log("debug");

Исчезает из итогового бандла.

Используется в production для снижения шума и размера.


drop_debugger

Удаляет инструкции debugger:

compress: {
  drop_debugger: true
}

pure_funcs

Позволяет указать функции без побочных эффектов:

compress: {
  pure_funcs: ["console.log", "debug"]
}

Если вызов считается чистым, он удаляется:

console.log("test");

Полностью исключается.


conditionals

Упрощение условных выражений:

compress: {
  conditionals: true
}

Пример:

const x = true ? 1 : 2;

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

const x = 1;

comparisons

Упрощает логические выражения:

compress: {
  comparisons: true
}

unused

Удаляет неиспользуемые переменные:

compress: {
  unused: true
}

Пример:

const a = 1;
const b = 2;
console.log(a);

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


sequences

Объединяет выражения:

compress: {
  sequences: true
}

Пример:

a = 1;
b = 2;

Становится:

a = 1, b = 2;

passes

Количество проходов оптимизации:

compress: {
  passes: 2
}

Большее значение усиливает оптимизацию, но увеличивает время сборки.


unsafe и side effects

compress: {
  unsafe: true
}

Позволяет более агрессивные преобразования, потенциально нарушающие поведение в редких случаях.

Используется только при полной уверенности в отсутствии побочных эффектов.


format.comments: управление комментариями

Назначение

Опция format.comments определяет, какие комментарии сохраняются в финальном бандле.


Полное удаление комментариев

format: {
  comments: false
}

Удаляет все комментарии без исключений.


Сохранение лицензий

Часто используется в open-source проектах:

format: {
  comments: /@license|@preserve|^!/
}

Сохраняет только важные юридические комментарии.


Функция фильтрации

format: {
  comments: function (node, comment) {
    return /@preserve|@license/.test(comment.value);
  }
}

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


Взаимодействие mangle и compress

mangle и compress работают совместно, но на разных уровнях:

  • compress изменяет структуру кода (AST)
  • mangle изменяет имена идентификаторов

Порядок важен:

  1. compress упрощает код
  2. mangle сокращает идентификаторы

Пример комбинированного эффекта:

Исходный код:

function sum(a, b) {
  const result = a + b;
  console.log(result);
  return result;
}

После compress:

function sum(a,b){const result=a+b;console.log(result);return result;}

После mangle:

function n(n,r){const e=n+r;console.log(e);return e}

Практическая конфигурация production

Типичная сбалансированная настройка:

new TerserPlugin({
  terserOptions: {
    mangle: {
      toplevel: true,
      keep_fnames: false,
      keep_classnames: false
    },
    compress: {
      drop_console: true,
      drop_debugger: true,
      dead_code: true,
      passes: 2
    },
    format: {
      comments: false
    }
  }
});

Ограничения и риски агрессивной минификации

Агрессивные настройки могут приводить к:

  • поломке кода, зависящего от имён функций
  • проблемам с сериализацией классов
  • нарушению логики библиотек с рефлексией
  • сложностям отладки после сборки

Особенно критичны:

  • mangle.toplevel
  • compress.unsafe
  • drop_console в отладочных окружениях

Производительность минификации

Параметры влияют на скорость сборки:

  • compress.passes увеличивает время экспоненциально
  • mangle относительно быстрый
  • compress — наиболее дорогая операция

Баланс между скоростью и размером бандла достигается экспериментально, в зависимости от проекта и требований к production-сборке.