Rollup как ядро Vite

В основе сборки production-артефактов в Vite лежит Rollup — модульный бандлер, ориентированный на работу с ES Modules и максимально агрессивную оптимизацию итогового кода. Такая архитектурная связка разделяет обязанности: Vite отвечает за дев-сервер и быстрые трансформации в режиме разработки, а Rollup берет на себя финальную сборку, где важны оптимизация, минимизация и корректное формирование графа зависимостей.

Подобное разделение позволяет избежать дублирования сложной логики бандлинга и использовать зрелую экосистему Rollup как основу production pipeline.


Причины выбора Rollup в качестве production-bundler

Rollup изначально проектировался вокруг ES Modules и статического анализа импортов. Это дает ключевое преимущество — возможность точного построения графа зависимостей без необходимости эмуляции CommonJS-динамики.

Основные свойства, определившие его роль в Vite:

  • Статический анализ импортов позволяет безопасно удалять неиспользуемый код
  • Эффективный tree-shaking на уровне AST
  • Нативная работа с ESM, без промежуточных абстракций
  • Предсказуемая модель плагинов
  • Гибкость генерации бандлов (esm, cjs, iife, umd)

Vite использует эти свойства для production-сборки, где критичны размер бандла и корректная оптимизация зависимостей.


Разделение ролей: Vite dev server и Rollup build pipeline

Архитектура Vite построена на разделении runtime-сценариев:

Режим разработки

В dev-режиме Vite не использует Rollup напрямую. Вместо этого применяется:

  • нативная обработка ES Modules в браузере
  • трансформация файлов через esbuild и плагины
  • динамическая подгрузка модулей по мере запроса

Такой подход обеспечивает мгновенный старт и отсутствие полной сборки проекта.

Production режим

При vite build включается Rollup-пайплайн:

  • построение полного графа модулей
  • применение плагинов Rollup
  • tree-shaking
  • code splitting
  • генерация итоговых ассетов

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


Граф модулей и роль Rollup в его построении

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

Процесс построения графа включает:

  • анализ import и export
  • разрешение путей через plugin resolver
  • связывание виртуальных модулей
  • определение entry points

В контексте Vite этот процесс дополняется специфическими слоями:

  • алиасы (resolve.alias)
  • виртуальные модули Vite plugins
  • pre-bundled dependencies из node_modules

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


Tree-shaking как центральный механизм оптимизации

Одним из ключевых преимуществ Rollup является глубокий tree-shaking на уровне AST.

Принцип работы:

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

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

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

  • barrel exports
  • условные re-export’ы
  • вспомогательные утилиты, не используемые конечным приложением

Code splitting и формирование чанков

Rollup в Vite отвечает за разделение кода на чанки в production-сборке.

Основные механизмы:

  • динамические import() как триггер разделения
  • общие зависимости, выносимые в shared chunks
  • vendor splitting через конфигурацию
  • оптимизация повторного использования модулей

Алгоритм построения чанков основан на анализе графа:

  • поиск точек разрыва (dynamic imports)
  • определение пересечений зависимостей
  • формирование минимальных пересекающихся наборов модулей

Это позволяет уменьшать дублирование кода между страницами и улучшать кешируемость.


Плагинная модель Rollup в контексте Vite

Плагины Rollup являются фундаментальной частью сборочного процесса Vite. Несмотря на наличие собственной плагинной системы Vite для dev-режима, production-сборка опирается на Rollup API.

Основные хуки:

  • resolveId — разрешение модулей
  • load — загрузка содержимого модуля
  • transform — трансформация AST/кода
  • renderChunk — постобработка чанков
  • generateBundle — финальная стадия генерации ассетов

Vite расширяет эту модель:

  • добавляет свои хуки поверх Rollup
  • синхронизирует dev и build плагины
  • обеспечивает совместимость плагинов между режимами

Интеграция Vite plugin API и Rollup pipeline

Плагины Vite часто выглядят как единый интерфейс, но внутри разделяются:

  • часть логики исполняется в dev-режиме
  • часть проксируется в Rollup

Это приводит к гибридной модели:

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

В production режиме Vite фактически передает управление Rollup, добавляя:

  • конфигурацию входных точек
  • резолверы
  • оптимизацию зависимостей
  • SSR/legacy настройки

Предобработка зависимостей и взаимодействие с Rollup

Перед запуском Rollup Vite выполняет этап dependency pre-bundling (обычно через esbuild). Однако итоговый граф все равно проходит через Rollup.

Задачи этого этапа:

  • конвертация CommonJS → ESM
  • устранение проблем с deep imports
  • ускорение холодного старта сборки
  • кэширование часто используемых пакетов

Rollup затем работает уже с нормализованным графом, что упрощает tree-shaking и оптимизацию.


Разрешение модулей и система резолвинга

Rollup в Vite использует расширенную систему резолвинга:

  • Node resolution алгоритмы
  • алиасы Vite
  • поддержка монорепозиториев
  • условные exports в package.json

Особую роль играют:

  • exports field resolution
  • fallback на deep imports (при разрешении Vite)
  • поддержка ESM/CJS hybrid пакетов

Это позволяет корректно собирать современные npm-экосистемы без ручной настройки.


Генерация итогового бандла

На финальном этапе Rollup выполняет генерацию output:

  • объединение модулей в чанки
  • минификация (через подключенные плагины)
  • генерация sourcemaps
  • хеширование файлов
  • оптимизация ассетов

Vite добавляет дополнительные шаги:

  • инъекция preload-модулей
  • генерация HTML-структуры
  • привязка ассетов к entry points

Производительность сборки и роль кеширования

Rollup в Vite используется с учетом агрессивного кеширования:

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

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


SSR и особые режимы сборки

В SSR-режиме Vite также использует Rollup, но с модифицированными настройками:

  • отключение части оптимизаций браузерного окружения
  • сохранение Node.js-совместимости
  • отдельные entry points для server bundle

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


Связь архитектурных уровней

Роль Rollup в Vite можно рассматривать как слой финальной детерминированной сборки поверх более динамичной dev-архитектуры:

  • Vite dev server — скорость, реактивность, минимальные преобразования
  • Rollup build — полнота анализа, оптимизация, стабильный output
  • плагинная система — мост между двумя режимами
  • dependency pre-bundling — подготовка графа для Rollup

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