Поля output.entryFileNames,
output.chunkFileNames и output.assetFileNames
управляют именованием файлов, которые генерирует Rollup во время сборки.
Эти параметры особенно важны в production-сборках, где требуется:
По умолчанию Rollup создаёт файлы с достаточно простыми именами, однако в реальных проектах почти всегда используется кастомная схема.
output.entryFileNamesentryFileNames определяет шаблон имени для entry-файлов
— то есть файлов, которые являются точками входа
(input).
Пример:
export default {
input: {
app: 'src/app.js',
admin: 'src/admin.js'
},
output: {
dir: 'dist',
format: 'es',
entryFileNames: 'js/[name].js'
}
};
Результат:
dist/
└── js/
├── app.js
└── admin.js
Entry-файлы:
input;Chunk-файлы:
Пример:
input: {
app: 'src/app.js'
}
// app.js
import('./dashboard.js');
В этом случае:
app.js — entry;dashboard-XXXX.js — chunk.[name]entryFileNames: '[name].js'
[name] — имя entry-модуля.
Пример:
input: {
main: 'src/main.js',
admin: 'src/admin.js'
}
Результат:
main.js
admin.js
entryFileNames: 'assets/js/[name].js'
Результат:
dist/
└── assets/
└── js/
├── main.js
└── admin.js
[hash]entryFileNames: 'js/[name]-[hash].js'
Результат:
js/main-A7FH2K.js
js/admin-L91SDA.js
Хэш зависит от содержимого файла.
Это используется для:
Можно ограничить длину:
entryFileNames: 'js/[name]-[hash:8].js'
Пример:
main-3f8a91bc.js
[format]entryFileNames: '[name].[format].js'
Результат:
main.es.js
main.cjs.js
Полезно при генерации нескольких форматов:
output: [
{
dir: 'dist/es',
format: 'es',
entryFileNames: '[name].[format].js'
},
{
dir: 'dist/cjs',
format: 'cjs',
entryFileNames: '[name].[format].js'
}
]
Часто используется такая схема:
entryFileNames: 'js/[name]-[hash].js'
Вместе с:
chunkFileNames: 'js/chunks/[name]-[hash].js',
assetFileNames: 'assets/[name]-[hash][extname]'
Результат:
dist/
├── js/
│ ├── app-AB12.js
│ └── chunks/
│ ├── vendor-X91A.js
│ └── dashboard-Z81Q.js
└── assets/
├── logo-K2A1.svg
└── style-P81F.css
output.chunkFileNameschunkFileNames определяет шаблон имён для автоматически
создаваемых чанков.
Пример:
chunkFileNames: 'chunks/[name]-[hash].js'
Chunk появляется при:
// main.js
button.oncl ick = async () => {
const module = await import('./dialog.js');
};
Rollup создаст:
main.js
dialog-XXXX.js
Имя dialog-XXXX.js контролируется через
chunkFileNames.
[name]chunkFileNames: 'chunks/[name].js'
Результат:
chunks/dialog.js
[hash]Production-конфигурация:
chunkFileNames: 'chunks/[name]-[hash].js'
Результат:
chunks/dialog-91AF7.js
Иногда Rollup не может определить осмысленное имя чанка.
Тогда появляются имена:
chunk-ABC123.js
или:
index-XYZ.js
Чтобы улучшить именование, используют:
manualChunks
manualChunksoutput: {
chunkFileNames: 'chunks/[name]-[hash].js'
},
manualChunks(id) {
if (id.includes('node_modules')) {
return 'vendor';
}
}
Результат:
chunks/vendor-ABCD.js
chunkFileNames: 'assets/chunks/[name]-[hash].js'
Результат:
assets/
└── chunks/
├── vendor-ABCD.js
└── dashboard-91FA.js
output.assetFileNamesassetFileNames отвечает за имена ассетов:
Ассетом становится любой файл, который Rollup эмитит как ресурс:
import './style.css';
import logo from './logo.svg';
assetFileNames: 'assets/[name]-[hash][extname]'
Результат:
assets/style-A91F.css
assets/logo-K81A.svg
[extname][extname] содержит расширение файла.
Пример:
assetFileNames: '[name][extname]'
Результат:
style.css
logo.svg
[ext][ext] возвращает расширение без точки.
Пример:
assetFileNames: 'assets/[name]-[hash].[ext]'
Результат:
assets/logo-ABCD.svg
assets/style-X91F.css
Очень распространённый подход:
assetFileNames: assetInfo => {
const ext = assetInfo.name.split('.').pop();
if (/png|jpg|svg|webp/.test(ext)) {
return 'images/[name]-[hash][extname]';
}
if (/woff|woff2|ttf/.test(ext)) {
return 'fonts/[name]-[hash][extname]';
}
if (ext === 'css') {
return 'css/[name]-[hash][extname]';
}
return 'assets/[name]-[hash][extname]';
}
Результат:
images/logo-A1B2.svg
fonts/inter-X91F.woff2
css/main-K81A.css
Все три поля:
entryFileNameschunkFileNamesassetFileNamesмогут принимать функцию.
entryFileNamesentryFileNames(chunkInfo) {
return `entries/${chunkInfo.name}-[hash].js`;
}
chunkInfoВ функции доступны данные о чанке:
{
facadeModuleId,
isDynamicEntry,
isEntry,
moduleIds,
name,
type
}
entryFileNames(chunkInfo) {
if (chunkInfo.name === 'admin') {
return 'admin/[name]-[hash].js';
}
return 'app/[name]-[hash].js';
}
assetFileNamesassetFileNames(assetInfo) {
console.log(assetInfo);
return 'assets/[name]-[hash][extname]';
}
assetInfo содержит:
{
name,
names,
originalFileName,
originalFileNames,
source,
type
}
Одна из наиболее популярных структур:
export default {
input: {
app: 'src/app.js',
admin: 'src/admin.js'
},
output: {
dir: 'dist',
format: 'es',
entryFileNames: 'js/[name]-[hash].js',
chunkFileNames: 'js/chunks/[name]-[hash].js',
assetFileNames: assetInfo => {
const ext = assetInfo.name
.split('.')
.pop();
if (/css/.test(ext)) {
return 'css/[name]-[hash][extname]';
}
if (/png|jpg|svg|webp/.test(ext)) {
return 'images/[name]-[hash][extname]';
}
if (/woff|woff2/.test(ext)) {
return 'fonts/[name]-[hash][extname]';
}
return 'assets/[name]-[hash][extname]';
}
}
};
dist/
├── css/
│ └── main-A91F.css
├── fonts/
│ └── inter-K12A.woff2
├── images/
│ └── logo-9FA1.svg
├── js/
│ ├── app-A81F.js
│ ├── admin-B12A.js
│ └── chunks/
│ ├── vendor-X91A.js
│ └── dialog-P81Q.js
└── assets/
└── manifest-Q81A.json
[name] при нескольких входахinput: {
public: 'src/public.js',
private: 'src/private.js'
}
entryFileNames: '[name].bundle.js'
Результат:
public.bundle.js
private.bundle.js
entryFileNames: '[name]/bundle.js'
Результат:
public/bundle.js
private/bundle.js
Иногда добавляют версию:
const version = '1.4.0';
entryFileNames: `js/[name]-${version}-[hash].js`
Результат:
js/app-1.4.0-ABCD.js
const buildDate = Date.now();
entryFileNames: `js/[name]-${buildDate}-[hash].js`
Без хэша:
app.js
Браузер может долго хранить файл в кеше.
С хэшем:
app-91AF7.js
После изменения содержимого:
app-7BC91.js
URL меняется, и браузер загружает новую версию.
chunkFileNamesЕсли не настроить chunk-файлы:
chunk-1.js
chunk-2.js
Такие имена:
При использовании:
sourcemap: true
Rollup создаёт:
app.js
app.js.map
Имя sourcemap строится автоматически на основе имени файла.
Для CDN обычно используют:
entryFileNames: 'js/[name]-[hash].js',
chunkFileNames: 'js/chunks/[name]-[hash].js',
assetFileNames: 'assets/[name]-[hash][extname]'
Преимущества:
[hash] у
entry и chunkХэш вычисляется отдельно.
Даже если:
main.js
vendor.js
связаны между собой, их хэши различаются.
assetFileNamesНеправильно:
assetFileNames: 'assets/[hash]'
Результат:
assets/A91F2
Файл теряет расширение.
Правильно:
assetFileNames: 'assets/[hash][extname]'
entryFileNames: '/js/[name].js'
Начальный / может привести к неожиданным путям.
Правильно:
entryFileNames: 'js/[name].js'
entryFileNames: '[name].js'
chunkFileNames: '[name].js'
Иногда это вызывает конфликты.
Особенно при совпадении имён entry и chunk.
Безопаснее:
entryFileNames: 'entries/[name].js',
chunkFileNames: 'chunks/[name].js'
preserveModulesПри:
preserveModules: true
Rollup сохраняет структуру модулей.
Тогда шаблоны начинают работать иначе.
Пример:
output: {
dir: 'dist',
preserveModules: true,
entryFileNames: '[name].js'
}
Структура будет близка к исходной.
Vite использует Rollup внутри production build.
Настройки передаются так:
export default defineConfig({
build: {
rollupOptions: {
output: {
entryFileNames: 'js/[name]-[hash].js',
chunkFileNames: 'js/chunks/[name]-[hash].js',
assetFileNames: 'assets/[name]-[hash][extname]'
}
}
}
});
output: {
dir: 'dist',
format: 'es',
entryFileNames: 'assets/[name]-[hash].js',
chunkFileNames: 'assets/[name]-[hash].js',
assetFileNames: 'assets/[name]-[hash][extname]'
}
Такой подход: