Внутреннее графовое представление в сборке формируется вокруг единого объекта компиляции, который превращает набор модулей в связный ориентированный граф зависимостей. Каждый импорт, require или динамическая загрузка становится ребром, а модуль — узлом. Именно на этом уровне Webpack 5 выполняет большую часть аналитической работы: определение достижимости кода, вычисление используемых экспортов, построение чанков и принятие решений о вырезании неиспользуемых фрагментов.
Внутренний граф Webpack 5 строится вокруг сущностей
Module, Dependency, Connection.
Каждый модуль содержит список зависимостей, а каждая зависимость при
резолве превращается в соединение между двумя модулями.
Ключевая идея заключается в том, что граф не является статической структурой. Он изменяется в процессе компиляции через последовательность фаз:
На этапе связывания формируется ModuleGraph, который
заменил более старую модель зависимостей из Webpack 4. Он хранит не
только связи модулей, но и контекст использования экспортов, причины
подключения модулей и метаданные о конкретных импортируемых
символах.
ModuleGraph в Webpack 5 является центральной структурой
анализа внутреннего графа. Он объединяет:
Каждый модуль получает представление о том, какие именно его экспорты используются. Это позволяет проводить тонкий tree-shaking на уровне отдельных символов, а не только целых файлов.
Структура опирается на обратные ссылки: не только модуль знает
зависимости, но и dependency хранит ссылку на исходный и целевой модуль
через connection.
Графовая модель используется для определения reachability. Процесс начинается с entry points, от которых выполняется обход графа:
Однако достижимость в Webpack 5 не бинарна. Существует несколько уровней включения:
Эта градация критична для последующих оптимизаций.
Inner Graph Analysis в Webpack 5 тесно связан с анализом экспортов на
уровне AST. Каждый модуль после парсинга формирует структуру
ExportInfo, которая затем попадает в ModuleGraph.
Каждый экспорт имеет статус:
Webpack строит цепочки re-export’ов, связывая символы через несколько модулей. Это позволяет отслеживать ситуацию вида:
export { a } from './moduleA';
где фактическое использование a определяется только в
конечной точке графа.
Анализ sideEffects напрямую влияет на форму внутреннего
графа. Если модуль помечен как:
"sideEffects": false
Webpack получает возможность вырезать узлы графа даже при отсутствии явного анализа экспортов.
В противном случае модуль становится “токсичным” для tree-shaking: он включается целиком при малейшем импорте.
На уровне графа это выражается так:
Это существенно влияет на плотность графа и количество включенных модулей.
Webpack 5 выполняет несколько уровней анализа связности:
Определяются статические связи import/export. Это основной слой графа, формирующий структуру зависимостей.
import() создает границы чанков. В графе появляются
разрывы, которые превращаются в отдельные chunk nodes.
require.context и условные импорты создают слабые ребра,
которые могут быть проигнорированы при оптимизации.
ChunkGraph является надстройкой над
ModuleGraph. Если ModuleGraph описывает связи модулей, то
ChunkGraph отвечает за упаковку этих модулей в финальные чанки.
Связь выражается следующим образом:
Inner Graph Analysis включает анализ того, как перемещение одного модуля влияет на весь граф чанков.
Каждое соединение в графе хранит не только связь модулей, но и контекст использования:
Эта информация позволяет выполнять локальные оптимизации без пересборки всего графа.
Удаление мертвого кода происходит не на уровне строк, а на уровне узлов графа и их экспортов.
Процесс включает:
Особенность Webpack 5 заключается в инкрементальном пересчете графа: изменения одного модуля не требуют полного пересоздания всей структуры.
Циклические зависимости не разрушают граф, но изменяют порядок анализа.
Webpack превращает цикл в strongly connected component:
Это позволяет корректно обрабатывать структуры вида взаимных импортов без потери информации о доступных экспортируемых значениях.
Inner Graph Analysis также включает оптимизацию структуры:
В результате граф становится менее глубоким и более широким, что улучшает производительность выполнения кода в runtime.
Webpack 5 использует кэширование на уровне графа. При изменении одного модуля:
Это критично для больших проектов, где полный пересчет графа может быть дорогим.
Граф не является чисто статическим. Runtime механизмы влияют на его структуру:
Таким образом, итоговый граф представляет собой комбинацию compile-time и runtime анализа, где часть структуры становится известной только во время выполнения приложения.