В конфигурации Rollup секция output определяет способ
формирования итоговой сборки. Два ключевых поля, отвечающих за место
вывода файлов:
output.fileoutput.dirНесмотря на похожее назначение, эти параметры используются в разных сценариях и не могут применяться одновременно в одной конфигурации вывода.
output.fileoutput.file используется, когда Rollup должен создать
один итоговый файл.
Пример:
export default {
input: 'src/index.js',
output: {
file: 'dist/bundle.js',
format: 'esm'
}
};
В результате будет создан один файл:
dist/
└── bundle.js
Такой режим подходит для:
output.fileПри использовании output.file Rollup:
Даже если проект состоит из десятков модулей:
src/
├── index.js
├── utils.js
├── api.js
└── components/
├── button.js
└── modal.js
Rollup всё равно создаст:
dist/
└── bundle.js
export default {
input: 'src/main.js',
output: {
file: 'public/app.js',
format: 'iife',
name: 'App'
}
};
Результат:
<script src="app.js"></script>
Внутри файла окажется весь код приложения.
output.fileoutput: {
file: 'dist/my-lib.js',
format: 'umd',
name: 'MyLib'
}
output: {
file: 'dist/bundle.min.js',
format: 'iife'
}
output: {
file: 'bin/cli.js',
format: 'cjs'
}
output: {
file: 'dist/app.js',
format: 'esm'
}
output.fileГлавное ограничение — невозможность полноценного code splitting.
Например:
export default {
input: 'src/index.js',
output: {
file: 'dist/bundle.js',
format: 'esm'
}
};
Если внутри проекта используется:
import('./lazy.js');
Rollup попытается создать отдельный chunk, но поле file
предполагает только один выходной файл.
В результате появится ошибка:
Invalid value for option "output.file"
when building multiple chunks
output.diroutput.dir используется, когда Rollup должен создавать
несколько файлов.
Пример:
export default {
input: 'src/index.js',
output: {
dir: 'dist',
format: 'esm'
}
};
Теперь Rollup получает возможность:
output.dirВместо одного файла Rollup управляет целой директорией.
Пример структуры результата:
dist/
├── index.js
├── vendor.js
├── chunk-A7F2.js
└── chunk-B91D.js
Каждый chunk создаётся автоматически.
output.dir нужен для code splittingCode splitting подразумевает наличие нескольких выходных файлов.
Пример:
// index.js
button.addEventListener('click', async () => {
const module = await import('./dialog.js');
module.openDialog();
});
Rollup разделит код:
dist/
├── index.js
└── dialog-83HF.js
Главный bundle будет загружать дополнительный chunk динамически.
Такое поведение невозможно с output.file.
export default {
input: {
main: 'src/main.js',
admin: 'src/admin.js'
},
output: {
dir: 'dist',
format: 'esm'
}
};
Результат:
dist/
├── main.js
├── admin.js
└── shared.js
Rollup автоматически вынесет общий код в отдельный chunk.
output.file и output.dir| Возможность | output.file | output.dir |
|---|---|---|
| Один bundle | Да | Да |
| Несколько chunks | Нет | Да |
| Code splitting | Нет | Да |
| Dynamic import | Ограничено | Да |
| Multiple entry points | Нет | Да |
| Shared chunks | Нет | Да |
| Простая структура | Да | Нет |
| Гибкость | Низкая | Высокая |
Попытка совместить dynamic import с output.file.
Пример:
export default {
input: 'src/index.js',
output: {
file: 'dist/bundle.js',
format: 'esm'
}
};
При наличии:
await import('./lazy.js');
Rollup сообщит:
To inline dynamic imports, use the
output.inlineDynamicImports option
inlineDynamicImportsИногда требуется сохранить output.file, но при этом
использовать dynamic import.
Для этого существует:
output: {
file: 'dist/bundle.js',
format: 'esm',
inlineDynamicImports: true
}
Теперь Rollup встроит динамические модули внутрь одного файла.
Однако:
output.dir
предпочтительнееСовременные frontend-приложения почти всегда используют:
Поэтому применяется:
output: {
dir: 'dist',
format: 'esm'
}
Например:
dist/
├── index.js
├── utils.js
├── dom.js
└── internal/
Rollup может выводить:
Всё это удобнее хранить через output.dir.
preserveModulespreserveModules сохраняет структуру модулей.
Пример:
export default {
input: 'src/index.js',
output: {
dir: 'dist',
format: 'esm',
preserveModules: true
}
};
Исходная структура:
src/
├── index.js
├── utils.js
└── core/
└── api.js
Результат:
dist/
├── index.js
├── utils.js
└── core/
└── api.js
Такой режим невозможен с output.file.
output.file для UMD и IIFEФорматы:
iifeumdобычно предполагают один итоговый файл.
Пример:
output: {
file: 'dist/library.js',
format: 'umd',
name: 'Library'
}
Причина:
output.dir для ESMФормат esm особенно хорошо сочетается с directory
output.
Пример:
output: {
dir: 'dist',
format: 'esm'
}
Потому что:
При использовании output.dir можно настраивать шаблоны
файлов.
Пример:
output: {
dir: 'dist',
format: 'esm',
chunkFileNames: 'chunks/[name]-[hash].js',
entryFileNames: 'entry/[name].js',
assetFileNames: 'assets/[name]-[hash][extname]'
}
Результат:
dist/
├── chunks/
├── entry/
└── assets/
output.file
прощеПреимущества:
Недостатки:
output.dir
сложнееПреимущества:
Недостатки:
Rollup позволяет создавать несколько вариантов сборки.
Пример:
export default {
input: 'src/index.js',
output: [
{
file: 'dist/library.cjs.js',
format: 'cjs'
},
{
dir: 'dist/esm',
format: 'esm'
}
]
};
Результат:
dist/
├── library.cjs.js
└── esm/
├── index.js
├── chunk.js
└── utils.js
file и diroutput.fileЕсли:
output.dirЕсли:
preserveModules;При output.file Rollup строит:
Graph -> Single Chunk -> File
При output.dir:
Graph -> Multiple Chunks -> Directory
Это фундаментальное различие механизма сборки.
Нельзя писать:
output: {
file: 'dist/app.js',
dir: 'dist'
}
Rollup выдаст ошибку конфигурации.
Причина:
file описывает один выходной файл;dir описывает контейнер для множества файлов.Эти стратегии несовместимы.
Многие плагины Rollup работают по-разному в зависимости от
file и dir.
Например:
При output.dir плагины получают больше возможностей, так
как Rollup управляет файловой структурой целиком.
output.file1 большой bundle
Плюсы:
Минусы:
output.dirнесколько специализированных chunks
Плюсы:
Минусы:
Для приложений чаще используется:
output.dir
Для библиотек:
output.file
или комбинированная стратегия:
output: [
{ file: 'dist/index.cjs.js', format: 'cjs' },
{ dir: 'dist/esm', format: 'esm' }
]
Такой подход обеспечивает: