Хук renderStart и renderChunk

В системе плагинов Rollup стадия рендеринга отделена от стадии построения графа модулей и разрешения зависимостей. После того как сформирован module graph, выполнены все трансформации и оптимизации, Rollup переходит к этапу генерации выходного кода. Именно здесь начинают работать хуки renderStart и renderChunk, которые относятся к финальной фазе сборки и ориентированы на управление процессом генерации итогового бандла.

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


renderStart: инициализация этапа генерации чанков

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

Сигнатура

renderStart(outputOptions, inputOptions)

Контекст выполнения

На этом этапе доступны:

  • финальные настройки вывода (outputOptions)
  • исходные настройки сборки (inputOptions)
  • информация о сформированном графе модулей (косвенно через API контекста плагина)

Однако отсутствует доступ к конкретным чанкам — они еще не сгенерированы.


Основные сценарии использования renderStart

Подготовка состояния плагина

renderStart часто используется для инициализации внутренних структур плагина, которые зависят от итоговой конфигурации сборки:

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

Валидация output-конфигурации

Плагин может проверять корректность конфигурации вывода:

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

Если в этот момент выбрасывается ошибка, генерация бандла прекращается до создания файлов.


Пример использования

export default function myPlugin() {
  return {
    name: 'my-plugin',

    renderStart(outputOptions, inputOptions) {
      if (outputOptions.format === 'iife' && outputOptions.sourcemap === true) {
        throw new Error('Sourcemaps не поддерживаются в данном формате');
      }

      this.state = {
        chunkCount: 0
      };
    }
  };
}

Особенности поведения renderStart

  • вызывается один раз на каждый output target
  • выполняется до создания любого чанка
  • не может модифицировать граф модулей
  • может прерывать сборку через исключение
  • имеет доступ к контексту плагина через this

renderChunk: трансформация каждого чанка

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

Сигнатура

renderChunk(code, chunk, outputOptions)

Параметры

  • code — строка с уже сгенерированным кодом чанка
  • chunk — объект с метаданными чанка (имя, зависимости, экспортируемые символы)
  • outputOptions — конфигурация вывода

Механика работы renderChunk

Rollup вызывает этот хук после:

  1. генерации AST-представления модуля
  2. объединения модулей в чанки
  3. применения tree-shaking
  4. генерации финального кода чанка

После выполнения всех плагинов результат может быть:

  • оригинальный код без изменений
  • модифицированный код
  • null (удаление чанка)
  • объект { code, map } (если изменяется source map)

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

Минификация или постобработка

Хотя обычно минификация делегируется специализированным плагинам, renderChunk может использоваться для легких преобразований:

  • удаление debug-логов
  • замена констант
  • внедрение runtime-хелперов
  • адаптация к специфике окружения

Инструментирование кода

Часто используется для внедрения измерений производительности:

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

Модификация экспортов

Плагин может изменять экспортируемое поведение модуля на уровне чанка:

  • добавление namespace-оберток
  • трансформация формата экспорта
  • внедрение совместимости с legacy-системами

Пример использования renderChunk

export default function debugPlugin() {
  return {
    name: 'debug-plugin',

    renderChunk(code, chunk) {
      const wrapped = `
        (function() {
          console.log('Chunk loaded:', '${chunk.name}');
          ${code}
        })();
      `;

      return {
        code: wrapped,
        map: null
      };
    }
  };
}

Удаление чанка через renderChunk

Если вернуть null, чанк не попадет в итоговую сборку:

renderChunk(code, chunk) {
  if (chunk.name === 'debug-only') {
    return null;
  }
}

Это используется для условной генерации кода, например:

  • debug/production разделение
  • платформенные сборки
  • feature flags

Работа с sourcemap

renderChunk может возвращать объект с source map:

renderChunk(code) {
  const transformed = code.replace('DEBUG', '');

  return {
    code: transformed,
    map: null
  };
}

При необходимости плагин может:

  • модифицировать существующую карту
  • генерировать новую
  • комбинировать карты нескольких трансформаций

Отличия renderStart и renderChunk

Уровень выполнения

  • renderStart — один раз на фазу рендеринга
  • renderChunk — многократно, для каждого чанка

Доступ к данным

  • renderStart — глобальная конфигурация
  • renderChunk — конкретный код и метаданные чанка

Возможности модификации

  • renderStart — только подготовка и валидация
  • renderChunk — изменение итогового кода

Влияние на производительность

renderChunk напрямую влияет на скорость сборки:

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

По этой причине:

  • тяжелые операции следует избегать
  • кэширование внутри плагина критично
  • сложные AST-манипуляции лучше переносить в transform

Порядок вызова в цепочке рендеринга

Типичный порядок выполнения на этапе генерации:

  1. renderStart
  2. генерация чанков
  3. renderChunk (для каждого чанка)
  4. запись файлов
  5. generateBundle (если используется)
  6. writeBundle (если используется)

Практическая модель использования в плагинах

renderStart и renderChunk часто используются совместно:

  • renderStart подготавливает состояние
  • renderChunk применяет его к каждому чанку

Пример связки:

export default function trackingPlugin() {
  return {
    name: 'tracking-plugin',

    renderStart() {
      this.startTime = Date.now();
    },

    renderChunk(code, chunk) {
      const time = Date.now() - this.startTime;

      return {
        code: `// chunk processed in ${time}ms\n${code}`,
        map: null
      };
    }
  };
}

Ограничения и особенности интеграции

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

Поведение при нескольких плагинах

Если несколько плагинов реализуют renderChunk, они выполняются цепочкой:

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

Использование в архитектуре Rollup-плагинов

renderStart и renderChunk закрывают pipeline Rollup:

  • buildStart / resolveId / load / transform — подготовка и сборка графа
  • renderStart — вход в генерацию
  • renderChunk — постобработка каждого файла

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