Режим наблюдения в esbuild предназначен для автоматического повторного выполнения сборки при изменении исходных файлов. В отличие от классических сборщиков, где watch часто реализуется как надстройка поверх пересборки проекта, esbuild изначально проектировался с акцентом на скорость и инкрементальность, что делает его модель наблюдения крайне легковесной и быстрой.
Ключевая особенность заключается в том, что watch не запускает сборку «с нуля» при каждом изменении. Вместо этого используется сохранённое состояние графа модулей, что позволяет пересобирать только затронутые части проекта.
Режим watch доступен в двух основных вариантах: через CLI и через программный API.
При использовании CLI достаточно добавить флаг
--watch:
esbuild src/index.js --bundle --outfile=dist/bundle.js --watch
В этом режиме esbuild:
CLI-режим прост, но ограничен в управлении поведением пересборки.
API предоставляет более гибкий контроль:
import * as esbuild from 'esbuild';
await esbuild.build({
entryPoints: ['src/index.js'],
bundle: true,
outfile: 'dist/bundle.js',
watch: {
onRebuild(error, result) {
if (error) {
console.error('Ошибка пересборки:', error);
} else {
console.log('Пересборка завершена');
}
}
}
});
В этом варианте:
onRebuild получает результат каждой последующей
сборки;Esbuild не использует универсальный polling-цикл по умолчанию. Вместо этого применяется системный механизм наблюдения за файлами:
При невозможности использования нативных API возможен fallback к периодическому опросу.
Отслеживание строится не на уровне всей директории, а на уровне конкретных файлов, включённых в граф зависимостей. Это снижает нагрузку на файловую систему.
Важно, что esbuild отслеживает:
import,
require);onLoad).В основе watch-режима лежит сохранение графа модулей между сборками.
После первой сборки esbuild сохраняет:
onResolve);onLoad);При изменении файла происходит:
Это позволяет избежать полной пересборки даже в крупных проектах.
При изменении содержимого файла пересобирается только поддерево зависимостей, которое связано с этим модулем. Если модуль является «листьевым», пересборка минимальна.
Добавление нового файла не вызывает пересборку всего проекта автоматически. Однако:
Удаление файла приводит к:
Переименование обрабатывается как комбинация удаления и добавления. Это может привести к более широкой пересборке, если зависимости не удаётся сопоставить автоматически.
В API режиме ключевым механизмом взаимодействия является
onRebuild.
watch: {
onRebuild(error, result) {
// обработка результатов
}
}
Объект result содержит:
Ошибки компиляции не останавливают watch-режим — он продолжает наблюдение за файлами.
Начиная с новых версий esbuild, предпочтение отдаётся Context API:
import * as esbuild from 'esbuild';
const ctx = await esbuild.context({
entryPoints: ['src/index.js'],
bundle: true,
outfile: 'dist/bundle.js'
});
await ctx.watch();
Context API изменяет модель работы:
Также доступен ручной запуск пересборки:
await ctx.rebuild();
Это позволяет:
Watch-режим в esbuild оптимизирован под минимальное время отклика.
onResolve и
onLoad;Дополнительно esbuild избегает избыточной сериализации данных между сборками, сохраняя внутренние структуры в памяти.
Несмотря на высокую скорость, режим наблюдения имеет архитектурные ограничения.
esbuild не предоставляет встроенного hot module replacement. При изменениях:
Система не анализирует изменения на уровне «функций» или «экспорта». Любое изменение файла приводит к инвалидированию модуля целиком.
В сложных средах (Docker, сетевые FS) наблюдение может работать менее стабильно из-за особенностей событий файловой системы.
Watch-режим часто используется совместно с сервером разработки.
Типичная схема:
Пример интеграции:
import * as esbuild from 'esbuild';
import http from 'http';
await esbuild.build({
entryPoints: ['src/index.js'],
bundle: true,
outfile: 'dist/bundle.js',
watch: {
onRebuild(err) {
if (!err) {
console.log('Обновление готово');
}
}
}
});
http.createServer((req, res) => {
res.end('dev server');
}).listen(3000);
В более сложных системах watch используется как источник событий для WebSocket-инвалидации страницы.
Watch-режим удерживает:
При долгом запуске это означает:
Остановка watch выполняется через завершение процесса или вызов
ctx.dispose() в Context API.