Размер итогового бандла в Rollup напрямую определяется тем, какие модули попадают в граф зависимостей и насколько агрессивно выполняется их отсечение. В отличие от многих других сборщиков, Rollup изначально ориентирован на работу с ES Modules, что делает возможным статический анализ импортов и эффективное tree-shaking.
Ключевое свойство, влияющее на размер выходного кода, — полная статичность структуры импортов. Любая динамика (require, условные импорты, побочные эффекты на уровне модулей) ухудшает возможности оптимизации.
Механизм tree-shaking в Rollup опирается на анализ:
Наиболее значимый фактор — корректная маркировка побочных эффектов.
В package.json критически важен флаг:
{
"sideEffects": false
}
или точечная настройка:
{
"sideEffects": [
"*.css",
"*.scss"
]
}
Если пакет помечен как имеющий побочные эффекты, Rollup вынужден сохранять больше кода, даже если он не используется.
Rollup удаляет:
Особенно эффективно это работает при использовании
const-структур и чистых функций без внешнего состояния.
Ключевой фактор уменьшения бандла — отказ от CommonJS зависимостей.
ESM позволяет:
При подключении CommonJS через @rollup/plugin-commonjs
часто теряется часть оптимизаций, поэтому предпочтение всегда отдается
ESM-версиям библиотек (например, lodash-es вместо
lodash).
Грамотная модульная структура снижает размер итогового бандла за счет локализации зависимостей.
Типичная ошибка — централизованные “barrel files”
(index.js с массовыми re-export). Они часто ухудшают
tree-shaking, если не настроены корректно.
Опция external в Rollup позволяет полностью исключить
библиотеки из бандла:
external: ['react', 'react-dom']
Это критично для:
Каждая внешняя зависимость уменьшает итоговый размер сборки линейно, но требует контроля runtime-загрузки.
Многие крупные библиотеки тянут за собой цепочки зависимостей. Для уменьшения бандла используются:
date-fns вместо
moment)Rollup автоматически выделяет чанки при использовании:
import('./module.js')
Это позволяет:
Важно учитывать, что слишком мелкое дробление приводит к росту overhead на загрузку файлов.
Опция output.manualChunks позволяет управлять логикой
разделения:
manualChunks(id) {
if (id.includes('node_modules')) {
return 'vendor';
}
}
Более точная стратегия — разделение по доменным зонам:
Это снижает дублирование кода между чанками.
Rollup сам по себе не выполняет агрессивную минификацию. Используется
@rollup/plugin-terser:
Ключевые оптимизации:
Некоторые оптимизации возможны только на уровне terser:
Вместо:
import _ from 'lodash';
используется:
import debounce from 'lodash/debounce';
или ESM-эквивалент:
import { debounce } from 'lodash-es';
Разница может составлять десятки килобайт.
Barrel-файлы часто приводят к:
Оптимальная стратегия — прямые импорты глубинных модулей.
Подключение polyfills часто резко увеличивает размер бандла.
Стратегии уменьшения:
@babel/preset-env с
useBuiltIns: 'usage'Rollup-плагин @rollup/plugin-babel позволяет
контролировать этот процесс, но ключевая оптимизация выполняется на
уровне Babel.
Terser поддерживает аннотации:
/*#__PURE__*/
Они позволяют безопасно удалять вызовы функций:
const instance = /*#__PURE__*/ createExpensiveObject();
Это особенно важно для React-компонентов и фабрик объектов.
Любой код, выполняющийся при импорте модуля, ухудшает tree-shaking:
// плохо
initTelemetry();
Лучше:
export function init() {
initTelemetry();
}
@rollup/plugin-node-resolve влияет на выбор версии
модулей:
Приоритет module позволяет получить ESM-версию
библиотеки, что уменьшает размер бандла.
CommonJS обертка увеличивает код за счет:
Минимизация достигается сокращением числа CJS-зависимостей.
Rollup автоматически выделяет shared chunks, но эффективность зависит от структуры импортов.
Если модули импортируют одни и те же зависимости разными путями, возможны дубли.
Стратегия:
Мелкие файлы (иконки, JSON-конфиги) можно встраивать:
Но чрезмерное использование увеличивает размер JS и ухудшает кеширование.
Крупные ассеты должны быть внешними:
Rollup plugins для этого позволяют контролировать порог инлайнинга.
Плагины анализа позволяют выявить:
Типичная проблема — скрытые зависимости через транзитивные импорты.
Наибольший вклад в размер обычно дают:
Крупные приложения выигрывают от строгого разделения:
Это уменьшает связность и улучшает tree-shaking.
Перенос части функциональности в динамические чанки снижает initial bundle:
Rollup позволяет тонко управлять поведением tree-shaking:
Отключение избыточных проверок может уменьшить итоговый размер, но требует уверенности в чистоте кода.
Режим preserveModules сохраняет структуру исходных
файлов, что полезно для библиотек.
Плюсы:
Минусы:
Минимизация бандла в Rollup достигается не отдельными настройками, а совокупностью решений: