Опция dropLabels в Esbuild предназначена для удаления
помеченных операторов (labeled statements) из итогового кода во время
сборки. Она позволяет исключать определённые блоки кода без
использования условной компиляции, переменных окружения или
дополнительных инструментов трансформации.
Механизм особенно полезен для удаления отладочной логики, временных диагностических блоков, тестового кода и различных служебных конструкций, которые не должны попадать в производственную сборку.
Опция появилась как лёгкий способ реализовать своеобразные «компиляционные маркеры», позволяющие Esbuild полностью удалять помеченные участки исходного кода.
JavaScript поддерживает специальные конструкции — метки (labels).
Простейший пример:
debug: {
console.log("Отладка");
}
Здесь debug является меткой для блока кода.
Также метки могут использоваться с циклами:
outerLoop:
for (let i = 0; i < 10; i++) {
for (let j = 0; j < 10; j++) {
if (j === 5) {
break outerLoop;
}
}
}
В обычном JavaScript метки применяются редко, однако Esbuild использует их как удобный механизм маркировки кода для последующего удаления.
Конфигурация через JavaScript API:
await esbuild.build({
entryPoints: ['src/index.js'],
bundle: true,
dropLabels: ['DEBUG'],
outfile: 'dist/app.js'
});
Исходный код:
DEBUG: {
console.log("Отладочная информация");
}
console.log("Основная логика");
Результат:
console.log("Основная логика");
Блок с меткой DEBUG полностью исчезнет из сборки.
Параметр принимает массив строк.
Пример:
await esbuild.build({
dropLabels: [
'DEBUG',
'TEST',
'DEV_ONLY'
]
});
Теперь будут удаляться все блоки, помеченные указанными идентификаторами.
Исходный код:
DEBUG: {
console.log("debug");
}
TEST: {
console.log("test");
}
DEV_ONLY: {
console.log("dev");
}
console.log("production");
Результат:
console.log("production");
Передача опции через командную строку:
esbuild src/index.js \
--bundle \
--drop-labels=DEBUG \
--outfile=dist/app.js
Несколько меток:
esbuild src/index.js \
--bundle \
--drop-labels=DEBUG,TEST,DEV_ONLY \
--outfile=dist/app.js
Поскольку Esbuild написан на Go, соответствующая возможность присутствует и в Go API.
Конфигурация:
result := api.Build(api.BuildOptions{
EntryPoints: []string{"src/index.js"},
Bundle: true,
DropLabels: []string{
"DEBUG",
"TEST",
},
Outfile: "dist/app.js",
})
Один из наиболее распространённых сценариев использования.
Исходный код:
DEBUG: {
console.log("User:", user);
console.log("Config:", config);
console.log("State:", state);
}
После сборки:
Весь блок удаляется.
В отличие от конструкции:
if (process.env.NODE_ENV !== 'production') {
console.log(user);
}
здесь отсутствует необходимость в дополнительном анализе условий и подстановке значений переменных окружения.
Часто требуется временно добавить объёмный код для исследования ошибок.
Пример:
DEBUG: {
const report = generateDebugReport();
saveReport(report);
sendDebugInfo(report);
console.log(report);
}
После применения dropLabels данный код исчезнет
полностью.
Преимущество заключается в том, что не остаётся даже следов вызовов функций или промежуточных переменных.
Во время разработки в проекте могут присутствовать локальные проверки.
Пример:
TEST: {
runBenchmark();
runMemoryTest();
runStressTest();
}
Для production-сборки:
dropLabels: ['TEST']
Результат:
Тестовые процедуры не попадут в финальный пакет.
Крупные проекты часто используют различные уровни служебной логики.
Пример:
DEBUG: {
logDebugInfo();
}
TEST: {
runTests();
}
ANALYTICS: {
collectMetrics();
}
console.log("Application");
Можно удалять только определённые группы:
dropLabels: ['DEBUG', 'TEST']
Результат:
ANALYTICS: {
collectMetrics();
}
console.log("Application");
dropВ Esbuild существует ещё одна опция — drop.
Пример:
drop: ['console']
Она удаляет вызовы console.*.
Однако dropLabels работает принципиально иначе.
dropУдаляет определённые конструкции:
console.log("test");
Результат:
dropLabelsУдаляет целые помеченные блоки:
DEBUG: {
console.log("test");
doSomething();
calculate();
}
Результат:
То есть удаляется не конкретный вызов, а вся секция.
Esbuild обладает механизмом удаления мёртвого кода (Dead Code Elimination).
Пример:
if (false) {
console.log("test");
}
Такой код может быть удалён оптимизатором.
Однако для этого необходимо, чтобы условие было известно на этапе сборки.
С dropLabels ситуация проще:
DEBUG: {
console.log("test");
}
Esbuild удаляет блок без анализа условий.
defineМногие проекты используют:
if (__DEV__) {
console.log("debug");
}
Конфигурация:
define: {
__DEV__: 'false'
}
После чего выполняется оптимизация.
Вариант с метками выглядит компактнее:
DEBUG: {
console.log("debug");
}
И конфигурация:
dropLabels: ['DEBUG']
Особенно удобно при наличии больших диагностических блоков.
Внутри метки может находиться любой код.
Пример:
DEBUG: {
if (user) {
for (const role of user.roles) {
console.log(role);
}
}
}
После сборки:
Все вложенные операторы удаляются вместе с блоком.
Метка может содержать вызовы функций:
DEBUG: {
initializeDebugTools();
}
После удаления:
Вызов функции не выполняется и не попадает в выходной файл.
Пример:
DEBUG: {
await fetch('/debug');
}
После применения dropLabels:
Асинхронная операция полностью исчезает из результата сборки.
Исходный модуль:
import { logger } from './logger.js';
DEBUG: {
logger.printAll();
}
export function start() {
console.log("started");
}
После удаления метки:
export function start() {
console.log("started");
}
Если импорт больше нигде не используется, Esbuild дополнительно может удалить его благодаря tree shaking.
Одна из основных причин использования dropLabels —
уменьшение размера итогового пакета.
Пример:
DEBUG: {
hugeDiagnosticFunction();
logEntireApplicationState();
generateDebugDump();
}
Удаление таких блоков позволяет:
Наиболее распространённые варианты:
DEBUG:
DEV:
TEST:
INTERNAL:
BENCHMARK:
PROFILING:
EXPERIMENTAL:
Обычно используются заглавные буквы, чтобы визуально отличать специальные метки от обычных идентификаторов JavaScript.
Если конфигурация содержит:
dropLabels: ['DEBUG']
код:
TEST: {
runTests();
}
останется без изменений.
Конфигурация:
dropLabels: ['DEBUG']
Код:
DEBUG_MODE: {
console.log("test");
}
не будет удалён.
Сравнение выполняется по точному имени.
Пример:
dropLabels: ['DEBUG']
Код:
debug: {
console.log("test");
}
останется в результате.
Корректное совпадение:
DEBUG: {
console.log("test");
}
DEBUG: {
printStoreState();
}
Такой подход делает код более читаемым, чем множество условных операторов.
EXPERIMENTAL: {
runPrototypeFeature();
}
Экспериментальная функциональность может легко исключаться из различных сборок.
BENCHMARK: {
benchmarkParser();
}
Производственный код остаётся чистым без необходимости удаления тестовых фрагментов вручную.
Например:
DEBUG
TEST
BENCHMARK
PROFILING
INTERNAL
Единый набор обозначений упрощает поддержку крупных проектов и делает конфигурацию сборки предсказуемой.
dropLabels хорошо сочетается с:
minify;tree shaking;define;drop;bundle;splitting.Типичная production-конфигурация:
await esbuild.build({
entryPoints: ['src/index.js'],
bundle: true,
minify: true,
treeShaking: true,
drop: ['console'],
dropLabels: [
'DEBUG',
'TEST',
'PROFILING'
],
outfile: 'dist/app.js'
});
В результате удаляются отладочные сообщения, тестовые блоки, профилировочные секции и неиспользуемый код, что позволяет получить максимально компактную производственную сборку.