Плагин в Esbuild представляет собой объект с функцией
setup, внутри которой регистрируются обработчики событий
сборки. Эти обработчики привязываются к различным этапам жизненного
цикла компиляции через build.onStart и
build.onEnd.
Базовая структура плагина выглядит следующим образом:
export const myPlugin = () => ({
name: 'my-plugin',
setup(build) {
build.onStart(() => {
// действия перед началом сборки
});
build.onEnd((result) => {
// действия после завершения сборки
});
}
});
Оба хука относятся к глобальному процессу сборки и не привязаны к отдельным файлам напрямую. Их задача — реагировать на начало и завершение процесса компиляции, включая повторные сборки в watch-режиме и при использовании incremental API.
Хук onStart вызывается перед каждой новой компиляцией.
Это включает:
build.onStart(async () => {
// подготовка данных
});
Ключевые особенности:
build.onStart(() => {
cache.clear();
});
build.onStart(async () => {
const config = await loadRemoteConfig();
globalThis.__BUILD_CONFIG__ = config;
});
build.onStart(() => {
console.log('Сборка началась');
});
В режиме watch хук вызывается при каждом изменении
файлов, что делает его точкой синхронизации между файловой системой и
внутренним состоянием сборщика.
Важно учитывать, что:
onStart может вызываться часто;onEnd вызывается после завершения сборки, независимо от
того, успешна она или содержит ошибки.
build.onEnd((result) => {
// обработка результата
});
Аргумент result содержит:
errors — массив ошибок компиляции;warnings — предупреждения;metafile — метаданные сборки (если включены);outputFiles — при использовании
write: false.build.onEnd((result) => {
if (result.errors.length > 0) {
console.error('Сборка завершилась с ошибками');
return;
}
console.log('Сборка успешна');
});
build.onEnd((result) => {
if (result.metafile) {
const meta = result.metafile;
for (const file in meta.outputs) {
console.log('Сгенерирован файл:', file);
}
}
});
Метаданные позволяют анализировать:
При конфигурации write: false результат сборки доступен
в памяти:
build.onEnd((result) => {
result.outputFiles.forEach(file => {
console.log(file.path, file.contents);
});
});
Это часто используется для:
Хуки образуют замкнутый цикл:
onStart — подготовка среды;onEnd — обработка результата.onStart всегда вызывается раньше
onEnd;onStart могут задерживать начало
сборки.Пример последовательности:
build.onStart(() => {
console.log('A: start');
});
build.onStart(() => {
console.log('B: start');
});
build.onEnd(() => {
console.log('A: end');
});
build.onEnd(() => {
console.log('B: end');
});
Оба хука поддерживают асинхронное выполнение, но поведение различается.
build.onStart(async () => {
await new Promise(r => setTimeout(r, 100));
});
build.onEnd(async (result) => {
await writeReport(result);
});
let cache = new Map();
build.onStart(() => {
cache.set('startedAt', Date.now());
});
build.onEnd((result) => {
cache.set('lastBuildErrors', result.errors.length);
});
build.onEnd((result) => {
if (result.errors.length === 0) {
notify('Build succeeded');
} else {
notify('Build failed');
}
});
let startTime;
build.onStart(() => {
startTime = Date.now();
});
build.onEnd(() => {
console.log('Время сборки:', Date.now() - startTime);
});
При использовании:
context.watch()context.rebuild()хуки работают как часть повторяющегося цикла.
Особенности:
onStart вызывается при каждом
rebuild;onEnd соответствует каждому результату;Если в onStart или onEnd возникает
исключение:
Рекомендуется изолировать критические операции:
build.onEnd(() => {
try {
riskyOperation();
} catch (e) {
console.error('Ошибка в плагине:', e);
}
});
onEnd;onStart не имеет информации о входных файлах;onStart и onEnd формируют каркас управления
сборочным процессом, вокруг которого строятся более специализированные
хуки:
onResolve — управление разрешением модулей;onLoad — загрузка и трансформация файлов.В отличие от них, данные хуки: