Запуск в режиме наблюдения

Режим наблюдения в Rollup предназначен для автоматической пересборки бандла при изменении исходных файлов. Он превращает одноразовую сборку в непрерывный процесс, в котором сборщик отслеживает файловую систему, реагирует на изменения модулей и пересобирает только затронутые части графа зависимостей.

Основой механизма выступает отслеживание зависимостей, построенных во время первичного запуска сборки. Rollup анализирует импортируемые модули, формирует граф и далее использует его как основу для инкрементальной пересборки.


Самый простой способ включить режим наблюдения — использовать флаг --watch в CLI:

rollup -c --watch

или при явном указании входного файла:

rollup src/index.js -o dist/bundle.js --format esm --watch

После запуска процесс не завершается, а продолжает работать, ожидая изменений в файловой системе.

При изменении любого файла из графа зависимостей Rollup автоматически инициирует пересборку и выводит обновлённый бандл.


Поведение при изменении файлов

После активации watch-режима Rollup выполняет следующие шаги:

  1. Выполняется первоначальная сборка.

  2. Строится граф зависимостей.

  3. Активируется наблюдение за файлами.

  4. При изменении файла:

    • определяется затронутая часть графа;
    • выполняется повторный анализ модулей;
    • пересобирается только необходимый набор чанков.

В простых проектах пересборка может быть полной, однако в более сложных графах Rollup старается минимизировать переработку.


Использование watch в конфигурации

Watch-режим может быть задан через конфигурационный файл rollup.config.js.

export default {
  input: 'src/index.js',
  output: {
    file: 'dist/bundle.js',
    format: 'esm'
  },
  watch: {
    include: 'src/**',
    exclude: 'node_modules/**',
    clearScreen: true
  }
};

Основные параметры watch-конфигурации

include / exclude

Позволяют ограничить набор файлов, за которыми ведётся наблюдение.

  • include — явно указывает, какие файлы отслеживать
  • exclude — исключает ненужные директории
watch: {
  include: 'src/**',
  exclude: 'src/**/*.test.js'
}

clearScreen

Определяет, очищать ли консоль при каждой пересборке.

watch: {
  clearScreen: false
}

При false история сборок сохраняется, что удобно для анализа логов.


Инкрементальная пересборка

Rollup не пересобирает проект «с нуля» в большинстве случаев. Вместо этого он:

  • переиспользует ранее построенный граф модулей;
  • пересчитывает только изменённые узлы;
  • обновляет зависимости вверх по цепочке импорта.

Это особенно важно для крупных приложений, где полная пересборка может занимать значительное время.


Watch через JavaScript API

Помимо CLI и конфигурации, watch-режим можно запустить через программный API:

import { watch } from 'rollup';

const watcher = watch({
  input: 'src/index.js',
  output: {
    file: 'dist/bundle.js',
    format: 'esm'
  }
});

Watcher возвращает объект, позволяющий управлять процессом сборки.


События watcher

Watcher генерирует события жизненного цикла сборки:

watcher.on('event', event => {
  if (event.code === 'START') {
    // началась сборка
  }

  if (event.code === 'BUNDLE_END') {
    // сборка завершена
  }

  if (event.code === 'ERROR') {
    // ошибка сборки
  }
});

Основные типы событий:

  • START — запуск новой сборки
  • BUNDLE_START — начало формирования бандла
  • BUNDLE_END — завершение сборки
  • END — завершение цикла
  • ERROR — ошибка во время сборки

Поведение при множественных изменениях

При серии быстрых изменений файлов Rollup применяет механизм debounce:

  • изменения агрегируются;
  • пересборка не запускается мгновенно на каждое событие файловой системы;
  • запускается одна оптимизированная пересборка после стабилизации изменений.

Это снижает нагрузку на CPU и файловую систему.


Влияние плагинов на watch-режим

Плагины Rollup могут участвовать в процессе наблюдения через хуки:

  • buildStart
  • load
  • transform
  • watchChange

Хук watchChange особенно важен, так как позволяет реагировать на изменения файлов вручную:

export default function myPlugin() {
  return {
    name: 'my-plugin',
    watchChange(id) {
      // обработка изменения файла
    }
  };
}

Некоторые плагины могут добавлять дополнительные файлы в список отслеживания, например при генерации виртуальных модулей.


Ограничения watch-режима

Watch-режим имеет ряд архитектурных ограничений:

1. Отслеживание только файловой системы

Rollup не отслеживает изменения в runtime-данных. Изменения должны происходить на уровне файлов.


2. Ограниченная параллельность

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


3. Зависимость от плагинов

Некоторые плагины могут нарушать инкрементальность, если:

  • генерируют динамические зависимости;
  • некорректно реализуют кеширование;
  • создают побочные эффекты при каждом build.

Работа с крупными проектами

В больших проектах watch-режим требует дополнительной настройки:

Ограничение области наблюдения

watch: {
  include: 'packages/app/src/**',
  exclude: 'packages/**/node_modules/**'
}

Разделение на несколько конфигураций

export default [
  {
    input: 'src/main.js',
    output: { file: 'dist/app.js', format: 'esm' }
  },
  {
    input: 'src/admin.js',
    output: { file: 'dist/admin.js', format: 'esm' }
  }
];

Каждая конфигурация может иметь собственный watch-процесс.


Интеграция с Node.js процессом

Watcher можно интегрировать в сервер разработки:

import { watch } from 'rollup';

const watcher = watch(config);

watcher.on('event', event => {
  if (event.code === 'BUNDLE_END') {
    console.log('Пересборка завершена');
  }
});

Типичный сценарий — запуск dev-сервера, который перезагружает приложение после завершения сборки.


Производительность watch-режима

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

  • размер графа зависимостей;
  • количество файлов;
  • глубина импортов;
  • используемые плагины;
  • активность файловой системы.

Оптимизации:

  • исключение node_modules;
  • минимизация числа входных точек;
  • использование кешируемых плагинов;
  • уменьшение количества трансформаций в transform.

Типичные сценарии использования

Watch-режим применяется в следующих ситуациях:

  • разработка библиотек;
  • разработка SPA;
  • сборка UI-компонентов;
  • локальная отладка ESM-модулей;
  • интеграция с dev-серверами (Express, Koa, Vite-like setups на Rollup).

Особенности работы с зависимостями

При изменении зависимого модуля Rollup поднимает пересборку вверх по графу:

  • изменился leaf-модуль;
  • обновляются все импортеры;
  • пересчитываются затронутые чанки;
  • минимизируются изменения выходного бандла.

Это поведение делает watch-режим эффективным даже при сложных цепочках импортов.


Поведение при ошибках

При возникновении ошибки сборки:

  • текущий процесс watch не завершается;
  • Rollup сохраняет состояние предыдущей успешной сборки;
  • после исправления ошибки происходит новая пересборка.
watcher.on('event', event => {
  if (event.code === 'ERROR') {
    console.error(event.error);
  }
});

Перезапуск watcher

Watcher может быть перезапущен программно:

watcher.close();

После закрытия процесса необходимо заново вызвать watch().


Использование с sourcemap

Watch-режим часто применяется вместе с source map:

output: {
  file: 'dist/bundle.js',
  format: 'esm',
  sourcemap: true
}

Это позволяет отслеживать изменения в исходных файлах напрямую в браузере или отладчике при каждой пересборке.


Связь watch-режима и кэша Rollup

Rollup использует внутренний кэш для ускорения повторных сборок:

  • модули сохраняются в памяти;
  • пересборка затрагивает только изменённые узлы;
  • повторный парсинг неизменённых файлов исключается.

При необходимости кэш может быть сброшен, что приводит к полной пересборке при следующем цикле.