Webpack формирует граф зависимостей, начиная с одной или нескольких точек входа. Каждая точка входа (entry) определяет, с какого файла начинается сборка отдельного фрагмента приложения. При этом итоговый бандл представляет собой набор чанков, которые могут пересекаться по зависимостям.
Базовая конфигурация с одной точкой входа выглядит следующим образом:
module.exports = {
entry: './src/index.js',
};
В этом случае Webpack строит единое дерево зависимостей и формирует один основной чанк (или несколько, если подключены дополнительные плагины оптимизации).
При переходе к нескольким точкам входа структура становится более сложной:
module.exports = {
entry: {
app: './src/app.js',
admin: './src/admin.js',
},
};
Каждая точка входа формирует собственный независимый чанк. Однако без дополнительной настройки общие зависимости дублируются между ними, что приводит к увеличению итогового размера сборки.
При наличии нескольких entry Webpack рассматривает каждый вход как отдельное дерево модулей. Если оба дерева используют одни и те же библиотеки, например:
// app.js
import lodash from 'lodash';
// admin.js
import lodash from 'lodash';
то без оптимизации lodash будет включён в оба бандла. Это приводит к:
Решение этой проблемы заключается в явном или автоматическом
выделении общих зависимостей. Одним из базовых механизмов управления
этим процессом является использование dependOn в
конфигурации entry.
dependOn позволяет явно указать, что одна точка входа
зависит от другой. Это создаёт промежуточный чанк, содержащий общие
модули, который переиспользуется несколькими entry.
Простейшая конфигурация:
module.exports = {
entry: {
shared: './src/shared.js',
app: {
import: './src/app.js',
dependOn: 'shared',
},
admin: {
import: './src/admin.js',
dependOn: 'shared',
},
},
};
В данной структуре:
shared формирует отдельный чанк;app и admin не включают общие зависимости
внутрь себя;shared.Webpack интерпретирует dependOn как указание на
предкомпилированный слой зависимостей. При построении графа:
dependOn.Таким образом создаётся иерархия:
shared
├── app
└── admin
Важно, что shared не является абстрактным псевдонимом —
это полноценный чанк, который может быть загружен отдельно или
автоматически подтянут зависимыми entry.
Механизм имеет ряд архитектурных ограничений, которые важно учитывать при проектировании сборки.
dependOn задаётся статически. Это означает, что:
Каждый entry может зависеть только от заранее определённых чанков. Попытка создать циклические зависимости приводит к ошибке сборки.
entry: {
a: { import: './a.js', dependOn: 'b' },
b: { import: './b.js', dependOn: 'a' }, // ошибка
}
При росте проекта необходимо поддерживать актуальность shared-чанков вручную. Это может привести к архитектурной инерции, если структура зависимостей часто меняется.
dependOn поддерживает массив значений, что позволяет
строить более сложные композиции:
module.exports = {
entry: {
vendor: './src/vendor.js',
runtime: './src/runtime.js',
app: {
import: './src/app.js',
dependOn: ['vendor', 'runtime'],
},
admin: {
import: './src/admin.js',
dependOn: ['vendor', 'runtime'],
},
},
};
В этом случае формируется несколько уровней абстракции:
vendor — сторонние библиотеки;runtime — инфраструктурный код;app и admin — прикладные модули.Архитектурно важно различать назначение entry и зависимых чанков:
Типичная ошибка — использование entry как универсального контейнера для всего общего кода. Это приводит к:
Разделение через dependOn напрямую влияет на стратегию кеширования в браузере.
Если выделен стабильный shared-чанк:
При отсутствии разделения любое изменение в коде может приводить к пересборке крупных бандлов, даже если логически изменился только один модуль.
Хотя dependOn решает задачу ручного выделения общих
зависимостей, он часто используется в комбинации с
SplitChunksPlugin.
Разница заключается в подходе:
dependOn — ручное управление графом entry;SplitChunksPlugin — автоматическое выделение общих
модулей.При совместном использовании важно избегать дублирования логики разделения, иначе возможны:
В крупных приложениях часто используется многоуровневая модель:
Базовый runtime-чанк:
Vendor-чанк:
Feature-чанки:
Ленивая подгрузка:
В такой архитектуре dependOn используется для фиксации
верхнего уровня графа, обеспечивая стабильность структуры и
предсказуемость загрузки.
Webpack runtime отвечает за связывание чанков в браузере. При использовании dependOn он:
Если shared-чанк не загружен, выполнение зависимого entry откладывается до его загрузки.
На практике часто встречаются следующие проблемы:
Когда один и тот же модуль указывается в нескольких dependOn-цепочках, но не вынесен в общий слой.
Создание множества entry ради мелких частей функционала вместо использования динамических импортов.
Попытка искусственно разложить приложение по entry без учёта реальных зависимостей модулей.
Механизм dependOn является переходным инструментом между
простой моделью «один entry — один бандл» и современными графовыми
подходами к сборке.
Он позволяет:
При этом он сохраняет прозрачность архитектуры, так как явно отражает связи между точками входа без скрытой магии автоматических оптимизаций.