Ассеты в Rollup представляют собой любые ресурсы, которые не являются JavaScript-кодом в чистом виде, но участвуют в сборке: изображения, шрифты, CSS-файлы, JSON, медиафайлы, а также сгенерированные на лету строки или бинарные данные. Работа с ними требует понимания того, как Rollup представляет такие ресурсы внутри графа модулей и каким образом они превращаются в итоговый бандл.
Внутри Rollup ассеты не являются полноценными модулями JavaScript. Вместо этого они могут быть:
Ключевая особенность заключается в том, что Rollup не навязывает единственный способ работы с ресурсами. Управление полностью делегируется плагинам через Plugin API.
Ассет в Rollup существует в двух состояниях:
Основной механизм создания ассетов в Rollup — функция
emitFile, доступная в контексте плагинов через
this.emitFile.
Она позволяет зарегистрировать новый файл, который будет включён в итоговый бандл независимо от графа JavaScript-модулей.
this.emitFile({
type: 'asset',
name: 'style.css',
source: 'body { margin: 0; }'
});
type: всегда 'asset' для ресурсовname: человекочитаемое имя файла (опционально)fileName: фиксированное имя выходного файла (если
требуется контроль)source: содержимое ассета (строка или Buffer)emitFile возвращает идентификатор ассета:
const id = this.emitFile({
type: 'asset',
source: 'export default "hello";'
});
Этот идентификатор используется для последующих операций, включая получение пути к файлу.
Rollup различает два вида emitted-объектов:
Эта разница критична:
| Тип | Содержимое | Участвует в графе |
|---|---|---|
| asset | CSS, изображения | нет |
| chunk | JS-код | да |
Ассеты не проходят через механизмы tree-shaking и не анализируются как код.
После эмиссии ассет не сразу имеет путь в файловой системе. Rollup сначала регистрирует его внутри внутреннего реестра.
Существует два ключевых способа обращения:
Возвращается при emitFile и используется для доступа к
ассету:
const ref = this.emitFile({
type: 'asset',
source: 'content'
});
Позволяет получить финальное имя файла:
const fileName = this.getFileName(ref);
На момент вызова генерации bundle Rollup ещё может не знать точное имя, если используются хэши или динамическое именование.
Часто ассеты не просто создаются, но и должны быть связаны с JavaScript-кодом. Типичный сценарий — генерация URL к файлу.
Пример логики плагина:
generateBundle(options, bundle) {
const ref = this.emitFile({
type: 'asset',
name: 'data.txt',
source: 'hello world'
});
const fileName = this.getFileName(ref);
bundle['entry.js'].code += `\nexport const url = "${fileName}";`;
}
Таким образом создаётся связь между JS и ассетом без прямого импорта.
Rollup не ограничивает способ представления ресурса. Плагин может выбрать стратегию:
Содержимое встраивается прямо в код:
export const img = "data:image/png;base64,...";
Преимущества:
Недостатки:
Файл выносится отдельно:
export const img = "/assets/image.hash.png";
Преимущества:
Недостатки:
Финальный этап обработки ассетов происходит в хукe
generateBundle.
На этом этапе:
emitFile уже зарегистрированыАссеты находятся в объекте bundle:
generateBundle(options, bundle) {
for (const [fileName, file] of Object.entries(bundle)) {
if (file.type === 'asset') {
// обработка ассета
}
}
}
Структура ассета:
{
type: 'asset',
fileName: 'style.hash.css',
source: 'body { margin: 0 }'
}
Rollup предоставляет гибкую систему именования через
output.assetFileNames.
Пример:
output: {
assetFileNames: 'assets/[name]-[hash][extname]'
}
Поддерживаются плейсхолдеры:
[name] — имя ассета[hash] — хэш содержимого[extname] — расширение файла[ext] — расширение без точкиПри этом итоговое имя формируется только на этапе генерации бандла, что влияет на момент разрешения референсов.
Некоторые плагины реализуют синтаксис импорта ассетов:
import url from './image.png';
Внутри плагина это преобразуется в:
const ref = this.emitFile({
type: 'asset',
source: <binary>
});
И затем заменяется на:
const url = getFileName(ref);
Таким образом импорт ассета фактически является синтаксическим
сахаром над emitFile.
Rollup может включать содержимое ассетов в хеш имени файла. Это создаёт важный эффект:
Хеш вычисляется на основе source ассета и параметров
сборки.
Финальное имя становится известно только после полной фазы генерации.
Жизненный цикл ассета проходит несколько стадий:
emitFileВажно, что до шага 3 ассет не имеет стабильного пути, что требует аккуратной работы с референсами.
Ассеты часто становятся точкой взаимодействия между плагинами:
Rollup гарантирует единый реестр emitted-файлов, что позволяет избегать конфликтов идентификаторов.
this.emitFile({
type: 'asset',
name: 'style.css',
source: cssString
});
this.emitFile({
type: 'asset',
name: 'data.json',
source: JSON.stringify(data)
});
this.emitFile({
type: 'asset',
name: 'version.txt',
source: version
});
Ассеты в Rollup выполняют функцию связующего слоя между JavaScript-графом и внешним миром. Они позволяют:
Их поведение определяется не ядром Rollup, а системой плагинов, что делает механизм гибким и расширяемым без изменения базовой архитектуры сборщика.