bundle.watchFiles: список отслеживаемых файлов

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

Назначение bundle.watchFiles

bundle.watchFiles представляет собой массив строк, содержащих абсолютные пути ко всем файлам, которые были задействованы в процессе формирования текущего бандла. Эти файлы считаются критическими для пересборки: любое изменение в них должно приводить к повторному запуску процесса bundle.generate() или bundle.write() в watch-режиме.

Ключевая особенность заключается в том, что список формируется динамически во время анализа графа модулей, а не задаётся пользователем напрямую. Rollup строит его на основе:

  • входных точек (input entry files),
  • импортов ES-модулей,
  • подключаемых ассетов (через плагины),
  • виртуальных модулей (если они зарегистрированы как зависимости),
  • дополнительных файлов, явно добавленных через API плагинов.

Таким образом, bundle.watchFiles отражает итоговую структуру зависимостей, а не конфигурацию сборки.


Формирование списка файлов в процессе сборки

Во время выполнения rollup.rollup() происходит построение графа модулей. На этом этапе Rollup последовательно:

  1. Загружает входной файл.
  2. Разбирает import-выражения.
  3. Рекурсивно обходит все зависимости.
  4. Регистрирует каждый обнаруженный файл в внутреннем кэше модулей.
  5. Добавляет путь к файлу в watch-набор.

Каждый модуль в графе сопровождается метаданными, включая:

  • путь к исходному файлу,
  • трансформированный код (если применялись плагины),
  • зависимости от других модулей,
  • дополнительные зависимости (secondary dependencies).

Именно из этих данных и формируется bundle.watchFiles.


Отличие от входной конфигурации

Важно различать bundle.watchFiles и input конфигурацию:

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

Например, при такой структуре:

main.js → utils.js → helpers.js → constants.js

input будет содержать только main.js, тогда как bundle.watchFiles включит:

  • main.js
  • utils.js
  • helpers.js
  • constants.js

Роль плагинов в расширении watchFiles

Плагины Rollup могут существенно влиять на состав bundle.watchFiles. Это происходит через добавление дополнительных зависимостей в процессе трансформации модулей.

Добавление файлов через this.addWatchFile

Плагины могут явно регистрировать дополнительные файлы, которые не участвуют в импортах, но должны отслеживаться:

  • конфигурационные файлы,
  • шаблоны,
  • внешние JSON или YAML ресурсы,
  • файлы генерации кода.

При вызове:

this.addWatchFile(path)

Rollup включает указанный файл в bundle.watchFiles.


Виртуальные модули и watchFiles

Виртуальные модули (создаваемые через плагины без физического файла на диске) не имеют собственного пути в файловой системе, однако могут зависеть от реальных файлов.

В этом случае:

  • сам виртуальный модуль не попадает в watchFiles,
  • но его зависимости, зарегистрированные через addWatchFile, попадают.

Это позволяет поддерживать корректную реакцию watch-режима даже при полностью программной генерации кода.


Использование в watch-режиме Rollup

В watch-режиме (rollup.watch) список bundle.watchFiles используется для:

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

При изменении любого файла из списка происходит:

  1. фиксация события изменения файловой системой,
  2. инвалидирование соответствующих модулей,
  3. частичное или полное пересоздание бандла,
  4. повторное формирование нового bundle.watchFiles.

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


Динамическая природа watchFiles

Содержимое bundle.watchFiles не является стабильным между сборками. Оно может изменяться в зависимости от:

  • условных импортов (import()),
  • ответвлений логики в плагинах,
  • окружения сборки (development/production),
  • ленивой загрузки модулей,
  • параметров конфигурации.

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


Влияние tree-shaking и исключения модулей

Tree-shaking влияет на состав графа модулей, а значит и на bundle.watchFiles.

Если модуль:

  • импортируется, но не используется,
  • и удаляется в процессе оптимизации,

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


Кэширование и watchFiles

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

  • изменения в watchFiles могут расширять кэш,
  • удалённые зависимости могут быть исключены,
  • неизменённые файлы сохраняют своё состояние между итерациями.

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


Практическая значимость

Хотя bundle.watchFiles чаще используется внутри Rollup и плагинов, его поведение критично для:

  • диагностики корректности watch-режима,
  • отладки плагинов,
  • анализа зависимостей проекта,
  • построения кастомных систем наблюдения за файлами.

В сложных сборочных пайплайнах этот список фактически становится отражением реального “живого” графа проекта в конкретный момент времени.


Особенности поведения в многопакетных сборках

При использовании нескольких входных точек или при сборке нескольких бандлов:

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

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


Ограничения и нюансы

Список bundle.watchFiles не предназначен для прямого изменения. Попытки модифицировать его вручную не влияют на поведение Rollup, так как он является результатом внутреннего анализа графа, а не входным параметром.

Также следует учитывать:

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