В Rollup предусмотрены механизмы, позволяющие добавлять произвольный код в начало и конец итогового бандла. Эти возможности реализуются через опции banner и footer, которые применяются на этапе генерации выходного файла и не требуют вмешательства в граф модулей или систему плагинов. Подобный подход используется для внедрения глобальных инициализационных конструкций, лицензий, обёрток окружения, патчей совместимости и других фрагментов, которые должны существовать вне основной структуры модулей.
На этапе генерации Rollup формирует единый текстовый результат, объединяя модули согласно графу зависимостей и применяя трансформации плагинов. После завершения композиции модулей в итоговый код выполняется постобработка, в рамках которой и применяются banner и footer.
banner вставляется в самое начало результирующего файла, до любого сгенерированного кода модулей.
footer добавляется в самый конец бандла, после всех модульных выражений и экспортов.
Обе опции работают на уровне строкового представления и не зависят от содержимого модулей, что делает их предсказуемыми и детерминированными.
В конфигурации Rollup опции задаются в объекте output:
export default {
input: 'src/index.js',
output: {
file: 'dist/bundle.js',
format: 'iife',
banner: '/* библиотека: core-utils */',
footer: '/* конец бандла */'
}
};
В результате сформированный файл будет иметь следующую структуру:
/* библиотека: core-utils */
(function () {
// сгенерированный код модулей
})();
/* конец бандла */
Важно, что banner и footer не обрабатываются транспайлерами внутри Rollup-графа и не проходят через плагины трансформации кода модулей.
Обе опции могут принимать функцию, возвращающую строку. Это позволяет учитывать параметры сборки, режимы окружения и метаданные.
export default {
output: {
file: 'dist/bundle.js',
format: 'esm',
banner: (chunkInfo) => {
return `/* build: ${chunkInfo.fileName} */`;
},
footer: (chunkInfo) => {
return `/* size: ${chunkInfo.modules.length} modules */`;
}
}
};
Объект chunkInfo содержит сведения о текущем чанке: имя файла, список модулей, их идентификаторы и прочие метаданные. Это позволяет формировать контекстно-зависимые вставки.
Функции вызываются на этапе генерации чанков, когда структура уже полностью сформирована. Это означает:
Таким образом, banner и footer являются исключительно постгенерационным слоем.
Основное назначение banner связано с добавлением информации, которая должна быть первой в файле.
Часто используется для вставки лицензий:
banner: `/*!
* Project Name
* (c) Company
* License: MIT
*/`
Такая информация должна располагаться до любого исполняемого кода, чтобы соответствовать требованиям распространения библиотек.
В редких случаях banner используется для внедрения минимальных патчей окружения:
banner: `;if (typeof window === 'undefined') { global.window = global; }`
Подобные конструкции применяются в сборках, рассчитанных на разные среды исполнения.
Banner может использоваться для внедрения метаданных:
banner: `/* build time: ${new Date().toISOString()} */`
Такая информация помогает при отладке и трассировке версий.
Footer используется для кода, который должен быть выполнен или объявлен после всех модулей.
В формате IIFE footer может использоваться для финальных вызовов:
footer: `;initApp();`
Такой код гарантированно выполнится после инициализации всех модулей.
В некоторых случаях footer применяется для модификации глобального состояния:
footer: `;window.__BUNDLE_LOADED__ = true;`
Это позволяет внешним системам отслеживать завершение загрузки бандла.
Footer может содержать shim-логики, которые должны быть доступны после основного кода:
footer: `
if (!Array.prototype.flat) {
Array.prototype.flat = function() { /* polyfill */ };
}
`
Поведение banner и footer зависит от формата сборки.
В этих форматах код оборачивается в функцию или универсальную обёртку, поэтому:
Это делает их внешними по отношению к модульной системе.
В формате ES modules:
Однако важно учитывать, что ESM требует строгой структуры, поэтому вставка должна быть синтаксически корректной.
В CommonJS:
Использование banner и footer связано с рядом ограничений, обусловленных их строковой природой.
Код в banner/footer не имеет доступа к API плагинов и не может взаимодействовать с графом модулей. Это исключает возможность:
Поскольку вставка выполняется как строка, некорректный синтаксис может нарушить весь бандл:
Особенно критично это для footer, так как он располагается в конце и может влиять на завершение выражений.
Хотя banner/footer обычно исключаются из tree-shaking, они могут:
В реальных проектах banner и footer часто применяются совместно с другими механизмами Rollup.
output: {
banner: process.env.NODE_ENV === 'production'
? '/* prod build */'
: '/* dev build */'
}
При code splitting каждая часть бандла может получать собственный banner/footer через chunk-level конфигурацию:
banner: (chunk) => `/* chunk: ${chunk.name} */`
Это позволяет идентифицировать отдельные части сборки.
В библиотечных сборках banner часто содержит:
Footer может содержать маркеры инициализации или совместимости с CDN-окружениями.
banner и footer не участвуют в генерации sourcemap как отдельные модули, однако их длина учитывается при расчёте смещений. Это означает, что:
Хотя banner и footer не проходят через transform-хуки, их наличие может косвенно влиять на плагины, работающие с финальным кодом:
Это делает их важным элементом финальной стадии сборки, несмотря на простоту механизма.
При активном использовании banner и footer в сложных сборках применяются определённые ограничения:
Такая практика снижает риск нарушения целостности итогового бандла и упрощает сопровождение сборки.