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 отвечает за сокращение имён переменных,
функций, классов и свойств объекта. Это один из ключевых механизмов
уменьшения размера итогового 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
}
mangle.toplevel включает переименование переменных и
функций в глобальной области видимости.
mangle: {
toplevel: true
}
Эффект:
Используется в максимально агрессивных production-сборках.
mangle: {
keep_fnames: true
}
Отключает переименование имён функций.
Применяется в случаях:
Function.namemangle: {
keep_classnames: true
}
Сохраняет имена классов без изменения.
Важные сценарии:
constructor.namemangle: {
safari10: true
}
Используется для обхода багов старых JS-движков, где агрессивный
mangle может ломать поведение let/const или
destructuring.
Позволяет исключить идентификаторы из минификации:
mangle: {
reserved: ["React", "Vue", "MyGlobal"]
}
Типичный сценарий — работа с глобальными библиотеками, где имя должно остаться неизменным.
compress выполняет анализ и преобразование дерева
синтаксиса (AST), удаляя лишние конструкции и упрощая выражения.
Это наиболее сложный и мощный этап минификации.
compress: {
dead_code: true,
drop_console: false,
drop_debugger: true
}
Удаление недостижимого кода:
compress: {
dead_code: true
}
Пример:
if (false) {
console.log("never executed");
}
После оптимизации блок полностью удаляется.
Удаление console.*:
compress: {
drop_console: true
}
Пример:
console.log("debug");
Исчезает из итогового бандла.
Используется в production для снижения шума и размера.
Удаляет инструкции debugger:
compress: {
drop_debugger: true
}
Позволяет указать функции без побочных эффектов:
compress: {
pure_funcs: ["console.log", "debug"]
}
Если вызов считается чистым, он удаляется:
console.log("test");
Полностью исключается.
Упрощение условных выражений:
compress: {
conditionals: true
}
Пример:
const x = true ? 1 : 2;
Преобразуется в:
const x = 1;
Упрощает логические выражения:
compress: {
comparisons: true
}
Удаляет неиспользуемые переменные:
compress: {
unused: true
}
Пример:
const a = 1;
const b = 2;
console.log(a);
b удаляется полностью.
Объединяет выражения:
compress: {
sequences: true
}
Пример:
a = 1;
b = 2;
Становится:
a = 1, b = 2;
Количество проходов оптимизации:
compress: {
passes: 2
}
Большее значение усиливает оптимизацию, но увеличивает время сборки.
compress: {
unsafe: true
}
Позволяет более агрессивные преобразования, потенциально нарушающие поведение в редких случаях.
Используется только при полной уверенности в отсутствии побочных эффектов.
Опция format.comments определяет, какие комментарии
сохраняются в финальном бандле.
format: {
comments: false
}
Удаляет все комментарии без исключений.
Часто используется в open-source проектах:
format: {
comments: /@license|@preserve|^!/
}
Сохраняет только важные юридические комментарии.
format: {
comments: function (node, comment) {
return /@preserve|@license/.test(comment.value);
}
}
Позволяет гибко управлять сохранением комментариев на основе содержимого.
mangle и compress работают совместно, но на
разных уровнях:
compress изменяет структуру кода (AST)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}
Типичная сбалансированная настройка:
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.toplevelcompress.unsafedrop_console в отладочных окруженияхПараметры влияют на скорость сборки:
compress.passes увеличивает время экспоненциальноmangle относительно быстрыйcompress — наиболее дорогая операцияБаланс между скоростью и размером бандла достигается экспериментально, в зависимости от проекта и требований к production-сборке.