Статический анализ графа модулей является центральным механизмом работы Rollup и определяет его фундаментальное отличие от других сборщиков модулей. В основе подхода лежит построение полного представления зависимостей проекта на этапе сборки без выполнения кода. Это позволяет точно определить, какие части приложения действительно используются, а какие могут быть безопасно исключены.
Процесс начинается с точки входа, указанной в конфигурации. Rollup анализирует этот модуль, извлекает из него импортируемые зависимости и рекурсивно переходит к каждому из них.
Каждый модуль рассматривается как узел графа, а импорт — как направленное ребро. В результате формируется ориентированный ациклический граф (DAG), где:
import / export;При этом анализ осуществляется исключительно на основе синтаксической структуры кода, без выполнения JavaScript в рантайме.
Каждый модуль проходит этап парсинга, в ходе которого код преобразуется в абстрактное синтаксическое дерево (AST). Rollup использует AST для точного извлечения:
import и export;AST служит основой для дальнейшего анализа связей между модулями и позволяет выполнять точечные трансформации без потери контекста.
После извлечения импортов Rollup выполняет процесс разрешения модулей. Он включает определение реального пути к каждому импортируемому ресурсу с учётом:
package.json (поле
exports);Результатом является построение полного списка модулей, участвующих в графе.
Когда все зависимости разрешены, Rollup формирует связанный граф, где каждый модуль содержит:
Особенность Rollup заключается в том, что граф строится с учётом конкретных используемых символов, а не только модулей целиком. Это обеспечивает более глубокий уровень анализа по сравнению с системами, которые оперируют только файловыми зависимостями.
Ключевой этап статического анализа — определение того, какие части кода действительно используются. Rollup выполняет анализ достижимости (reachability analysis), начиная с точки входа.
Процесс включает:
export { ... } from.Если символ не достигается из точки входа ни по одной цепочке зависимостей, он считается мёртвым кодом.
На основе построенного графа и анализа достижимости Rollup выполняет tree-shaking. В отличие от поверхностной фильтрации файлов, здесь учитывается:
Если модуль содержит побочные эффекты, он может быть частично или полностью сохранён, даже если его экспорты не используются.
Хотя граф модулей стремится к ацикличности, в реальных проектах возможны циклические зависимости. Rollup обрабатывает их путём:
Циклы не разрушают анализ, но усложняют определение порядка выполнения и требуют дополнительной нормализации графа.
Rollup учитывает конструкции вида:
export * fromexport { a, b } fromТакие случаи приводят к необходимости трансформации графа, при которой:
В результате граф становится более плоским, что упрощает финальную генерацию бандла.
Плагинная система Rollup может модифицировать граф на разных этапах:
Это делает граф не только результатом синтаксического анализа, но и результатом последовательной цепочки трансформаций.
После завершения анализа Rollup выполняет финальную оптимизацию графа:
Эти шаги подготавливают структуру к финальной стадии — генерации выходного кода.
Граф модулей напрямую определяет структуру итогового бандла. Порядок включения кода, область видимости переменных и структура обёрток формируются на основе топологии графа.
Каждый узел графа преобразуется в фрагмент итогового кода, а рёбра определяют порядок и способы связывания этих фрагментов. Таким образом, результат сборки является прямым отображением статически построенной структуры зависимостей.