В Rollup механизм code splitting опирается на граф модулей: каждый импорт формирует зависимости, а итоговая сборка может быть разделена на отдельные файлы (chunks). Это позволяет оптимизировать загрузку, кеширование и уменьшить первоначальный бандл.
Опция output.manualChunks управляет тем, как именно
Rollup группирует модули в чанки. Когда она задана как функция,
появляется возможность программно контролировать структуру сборки на
уровне каждого модуля.
manualChunksФункция вызывается для каждого модуля в графе:
manualChunks(id, meta)
Где:
id — абсолютный путь к модулю или виртуальный
идентификаторmeta — объект с дополнительной информацией о модуле (в
частности, getModuleInfo)Возвращаемое значение:
string — имя чанка, в который нужно поместить
модульundefined — оставить решение Rollup (автоматическое
размещение)undefinedКогда manualChunks задан как функция, Rollup переходит в
режим ручного распределения модулей. Логика выглядит так:
undefined, Rollup применяет стандартные
алгоритмы (например, vendor splitting при динамическом импорте)Важно: функция не влияет на порядок выполнения кода напрямую, она влияет только на структуру файлов.
Один из самых распространённых сценариев — отделение зависимостей из
node_modules.
export default {
input: 'src/main.js',
output: {
dir: 'dist',
format: 'esm',
manualChunks(id) {
if (id.includes('node_modules')) {
return 'vendor';
}
}
}
};
Результат:
vendor.jsТакой подход улучшает кеширование: зависимости меняются реже, чем собственный код проекта.
Более точный контроль достигается разбиением по конкретным пакетам.
manualChunks(id) {
if (id.includes('node_modules')) {
if (id.includes('lodash')) return 'lodash';
if (id.includes('react')) return 'react';
return 'vendor';
}
}
Так формируются отдельные чанки:
lodashreactvendorЭто особенно полезно в больших приложениях, где разные зависимости обновляются независимо.
Функция manualChunks позволяет реализовать архитектурное
разделение кода.
manualChunks(id) {
if (id.includes('/src/pages/')) {
return 'pages';
}
if (id.includes('/src/components/')) {
return 'components';
}
if (id.includes('/src/utils/')) {
return 'utils';
}
}
В результате:
Такой подход помогает при частичной загрузке приложения и улучшает параллелизм загрузки.
getModuleInfoВторой аргумент функции даёт доступ к информации о модуле:
manualChunks(id, { getModuleInfo }) {
const info = getModuleInfo(id);
}
Через getModuleInfo можно:
Пример выделения общих зависимостей:
manualChunks(id, { getModuleInfo }) {
const info = getModuleInfo(id);
if (info && info.importers && info.importers.length > 5) {
return 'common';
}
}
Здесь модули, которые используются в нескольких местах, попадают в общий чанк.
В сложных приложениях часто используется доменная архитектура.
manualChunks(id) {
if (id.includes('/auth/')) return 'auth';
if (id.includes('/billing/')) return 'billing';
if (id.includes('/dashboard/')) return 'dashboard';
}
Такой подход позволяет:
manualChunks над автоматикой RollupКогда функция возвращает имя чанка, Rollup перестаёт использовать стандартную эвристику для данного модуля. Это означает:
Если несколько правил возвращают разные значения для одного и того же модуля, учитывается первое сработавшее условие в коде функции.
Если разные условия возвращают разные чанки для связанных модулей, можно получить:
Чрезмерное количество чанков приводит к:
Использование относительных путей без нормализации может ломать сборку:
id.includes('../utils/')
Такой код чувствителен к структуре проекта и легко становится источником ошибок.
manualChunks особенно эффективно работает вместе с
динамическими импортами:
const module = await import('./features/analytics.js');
Rollup:
manualChunks для группировки
зависимостейВ результате можно контролировать как точку загрузки, так и структуру зависимостей внутри неё.
Один из устойчивых подходов:
manualChunks(id) {
if (id.includes('node_modules')) {
return 'vendor';
}
if (id.includes('/src/shared/')) {
return 'shared';
}
}
Итоговая структура:
vendor — внешние зависимостиshared — переиспользуемые модулиПравильная стратегия manualChunks влияет на:
Чем стабильнее границы чанков, тем выше эффективность кеширования.
В продвинутых конфигурациях используется анализ графа:
manualChunks(id, { getModuleInfo }) {
const info = getModuleInfo(id);
if (!info) return;
const isUsedOnlyByAuth = info.importers?.every(i =>
i.includes('/auth/')
);
if (isUsedOnlyByAuth) {
return 'auth-only';
}
}
Такие подходы позволяют строить почти статический анализ зависимостей прямо на этапе сборки.
Использование функции manualChunks фактически превращает
конфигурацию Rollup в слой архитектурного проектирования:
Это делает сборку не просто техническим этапом, а частью проектирования системы.