Программный API Rollup

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

Основой программного API является функция rollup, возвращающая объект сборки (bundle), через который выполняются генерация и запись выходных файлов. В отличие от декларативного конфигурационного подхода, программный API даёт полный контроль над жизненным циклом сборки, включая этапы компиляции, трансформации, генерации и вывода артефактов.


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

import { rollup } from 'rollup';

const bundle = await rollup({
  input: 'src/index.js',
  plugins: []
});

Ключевое свойство input определяет точку входа. В отличие от CLI-режима, здесь результат возвращается как объект, позволяющий продолжить работу с бандлом программно.


Объект bundle и его роль

Результат вызова rollup() — это объект bundle, содержащий методы управления сборкой:

  • generate(outputOptions) — генерация кода в памяти
  • write(outputOptions) — запись файлов на диск
  • close() — освобождение ресурсов
  • watchFiles — список файлов, участвующих в сборке (доступно в некоторых режимах)

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


Генерация кода без записи

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

const result = await bundle.generate({
  format: 'esm'
});

console.log(result.output);

Структура результата включает массив output, где каждый элемент представляет chunk или asset. Каждый chunk содержит сгенерированный код, карту источников (если включено sourcemap) и метаданные.


Запись результата на диск

Метод write выполняет генерацию и запись файлов:

await bundle.write({
  dir: 'dist',
  format: 'cjs'
});

Поддерживаются различные варианты вывода:

  • file — единый файл
  • dir — директория с чанками
  • entryFileNames, chunkFileNames, assetFileNames — шаблоны именования

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


Конфигурация через программный API

Все параметры конфигурации доступны и в программном API. Наиболее важные из них:

  • input — точка входа или несколько входов
  • external — исключение модулей из бандла
  • plugins — список плагинов
  • treeshake — управление tree-shaking
  • context — контекст выполнения для AMD/IIFE сборок
const bundle = await rollup({
  input: ['src/a.js', 'src/b.js'],
  external: ['fs', 'path'],
  treeshake: true
});

Плагины в программном API

Плагины являются ключевым механизмом расширения Rollup. В программном API они передаются напрямую в конфигурацию:

import resolve from '@rollup/plugin-node-resolve';

const bundle = await rollup({
  input: 'src/index.js',
  plugins: [
    resolve()
  ]
});

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

  • buildStart
  • resolveId
  • load
  • transform
  • generateBundle

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


Работа с sourcemap

Программный API позволяет тонко управлять генерацией sourcemap:

const result = await bundle.generate({
  format: 'esm',
  sourcemap: true
});

В результате каждый chunk содержит поле map, представляющее исходную карту преобразований. Это особенно важно при интеграции с дебаггерами и системами мониторинга кода.


Инкрементальная сборка и watch API

Rollup поддерживает режим наблюдения за изменениями через отдельный API:

import { watch } from 'rollup';

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

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

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

Каждое событие позволяет строить собственные системы логирования, уведомлений или hot-reload механизмов.


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

Rollup поддерживает кеширование предыдущих сборок для ускорения последующих запусков:

let cache;

const bundle = await rollup({
  input: 'src/index.js',
  cache
});

cache = bundle.cache;

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


Управление жизненным циклом сборки

После завершения работы с bundle рекомендуется освобождать ресурсы:

await bundle.close();

Это особенно важно в долгоживущих процессах, где создаётся множество сборок подряд, например в CI-системах или серверных компиляторах.


Обработка нескольких сборок

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

const [bundleA, bundleB] = await Promise.all([
  rollup({ input: 'src/a.js' }),
  rollup({ input: 'src/b.js' })
]);

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


Взаимодействие с виртуальными модулями

Через плагины программный API может создавать виртуальные модули, которые не существуют на файловой системе:

const virtual = () => ({
  name: 'virtual-module',
  resolveId(id) {
    if (id === 'virtual') return id;
  },
  load(id) {
    if (id === 'virtual') return 'export const msg = "hello"';
  }
});

const bundle = await rollup({
  input: 'src/index.js',
  plugins: [virtual()]
});

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


Расширенные output-опции

Программный API поддерживает все режимы вывода Rollup:

  • ESM
  • CommonJS
  • AMD
  • IIFE
  • System
await bundle.write({
  dir: 'dist',
  format: 'cjs',
  exports: 'auto',
  sourcemap: true
});

Параметр exports управляет способом экспорта в CommonJS, а interop контролирует взаимодействие с ES-модулями.


Обработка ошибок

Ошибки в программном API возвращаются как исключения:

try {
  const bundle = await rollup(config);
} catch (err) {
  console.error(err);
}

Ошибки могут возникать на этапах:

  • резолва модулей
  • трансформации
  • генерации кода

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


Контроль модульного графа

Программный API позволяет косвенно влиять на граф зависимостей через плагины. Rollup строит граф начиная с input, рекурсивно разрешая зависимости через import и export.

Каждый узел графа проходит стадии:

  • resolution
  • loading
  • transformation
  • inclusion in bundle

Этот процесс полностью управляется внутри rollup() и может быть расширен через плагины, но не изменяется напрямую извне API.


Производственные сценарии использования API

Программный API применяется в:

  • системах SSR-сборки
  • кастомных build-серверах
  • генерации библиотек на лету
  • интеграции с фреймворками
  • тестовых окружениях сборки

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