Rollup давно перестал быть только самостоятельным CLI-инструментом для сборки библиотек. Его архитектура, основанная на графе модулей и системе плагинов, сделала его удобным ядром для интеграции в другие системы сборки, фреймворки и инструменты разработки. Встраивание Rollup позволяет использовать его сильные стороны — предсказуемую ESM-сборку, tree-shaking и гибкую трансформацию кода — внутри более крупных пайплайнов.
Ключевая идея интеграции заключается в том, что Rollup рассматривается не как отдельный процесс, а как программный модуль, управляемый через JavaScript API. Это позволяет другим инструментам управлять этапами сборки, перехватывать результат, модифицировать конфигурацию и комбинировать Rollup с альтернативными трансформерами.
Основной способ использования Rollup внутри других инструментов — это
его JavaScript API. Вместо вызова CLI создаётся программная сборка через
функции rollup() и bundle.generate() или
bundle.write().
Ключевая функция:
rollup(inputOptions) — создаёт объект бандла на основе
конфигурацииПример архитектурного использования:
import { rollup } from 'rollup';
const bundle = await rollup({
input: 'src/index.js',
plugins: []
});
const result = await bundle.generate({
format: 'esm'
});
Этот подход позволяет встроить Rollup в любой Node.js-инструмент: сборщики, тестовые раннеры, генераторы статических сайтов, CLI-фреймворки.
Многие инструменты используют Rollup как внутренний движок для модульной сборки, добавляя поверх него собственную логику:
Типичный пример — кастомный build-tool, который оборачивает Rollup:
import { rollup } from 'rollup';
export async function buildProject(config) {
const bundle = await rollup({
input: config.entry,
plugins: config.plugins
});
await bundle.write({
file: config.output,
format: config.format
});
}
Такая обёртка позволяет скрыть сложность Rollup-конфигурации и превратить его в часть более высокоуровневого API.
Фреймворки и мета-инструменты используют Rollup для сборки пользовательских приложений или библиотек, особенно в случаях, когда требуется строгий контроль над выходным бандлом.
Типичные сценарии:
Во многих случаях Rollup используется как этап внутри пайплайна, где до него выполняются:
После этого Rollup принимает уже подготовленный набор модулей и формирует финальный граф.
Некоторые инструменты используют Rollup не для финальной сборки, а как промежуточный анализатор модулей. Это возможно благодаря тому, что Rollup строит полный граф зависимостей.
Такие сценарии включают:
Пример использования только для анализа:
import { rollup } from 'rollup';
const bundle = await rollup({
input: 'src/index.js'
});
const modules = await bundle.generate({
format: 'esm'
});
console.log(modules.output[0].modules);
В этом случае Rollup работает как инструмент статического анализа, а не как финальный бандлер.
Task runner системы используют Rollup как один из шагов конвейера задач. В таких архитектурах Rollup запускается:
Пример интеграции:
import { rollup } from 'rollup';
import terser from '@rollup/plugin-terser';
async function build() {
const bundle = await rollup({
input: 'src/index.js',
plugins: [terser()]
});
await bundle.write({
file: 'dist/bundle.js',
format: 'iife'
});
}
Task runner управляет этим процессом, добавляя параллелизм, логирование и обработку ошибок.
Dev-серверы используют Rollup для сборки в режиме разработки, часто вместе с watch API.
Основные сценарии:
Rollup предоставляет метод watch, который используется
для интеграции с файловыми наблюдателями:
import { watch } from 'rollup';
const watcher = watch({
input: 'src/index.js',
output: {
file: 'dist/bundle.js',
format: 'esm'
}
});
watcher.on('event', event => {
if (event.code === 'BUNDLE_END') {
console.log('Сборка завершена');
}
});
Dev-сервер оборачивает этот механизм и добавляет поверх него HTTP-слой и обработку модулей в реальном времени.
В сложных системах Rollup может использоваться совместно с другими сборщиками, например esbuild или Webpack. Это создаёт гибридные пайплайны:
Такой подход позволяет распределить задачи:
Пример архитектуры:
TypeScript → esbuild → Rollup → Terser → output
Rollup часто используется как ядро плагинной архитектуры в сторонних инструментах. Его плагинная модель достаточно универсальна:
resolveIdloadtransformgenerateBundleЭти хуки позволяют инструментам перехватывать процесс сборки на любом этапе.
Пример интеграции кастомного плагина:
function customPlugin() {
return {
name: 'custom-plugin',
transform(code, id) {
return code.replace('__VERSION__', '1.0.0');
}
};
}
Встраивание Rollup в другие системы часто означает расширение этих хуков дополнительной логикой: кэшированием, асинхронными операциями, взаимодействием с внешними сервисами.
При использовании Rollup внутри других инструментов ключевым становится управление конфигурацией программно.
Конфигурация может:
Пример динамической генерации:
export function createRollupConfig(env) {
return {
input: env.entry,
plugins: [
env.production && terser()
].filter(Boolean)
};
}
Такой подход позволяет унифицировать сборку для разных режимов без ручного изменения конфигурационных файлов.
Несмотря на гибкость, интеграция Rollup внутри других инструментов имеет ограничения:
Эти ограничения часто компенсируются внешними системами: worker threads, кеширующими слоями и предварительной обработкой модулей.
В современных build-системах Rollup часто занимает позицию «финального оптимизатора». Его используют не как первичный инструмент, а как завершающий этап, обеспечивающий:
Это делает его особенно полезным в сложных пайплайнах, где важно сохранить контроль над конечным результатом, несмотря на множество промежуточных трансформаций.