Опция entryNames в Esbuild управляет шаблоном именования
выходных файлов, создаваемых из входных точек входа (entry points). Она
используется только при включённом режиме раздельной генерации файлов
через параметр outdir и позволяет гибко формировать
структуру итоговой сборки.
По умолчанию Esbuild сохраняет имя выходного файла на основе имени исходного файла. Однако в крупных проектах этого часто недостаточно. Возникает необходимость:
Опция entryNames решает эти задачи посредством
специальных шаблонов.
await esbuild.build({
entryPoints: ['src/index.js'],
bundle: true,
outdir: 'dist',
entryNames: '[name]'
});
В данном случае имя результирующего файла будет сформировано из имени входного файла:
src/index.js
↓
dist/index.js
Значение entryNames представляет собой строку-шаблон,
содержащую специальные плейсхолдеры.
Пример:
entryNames: 'js/[name]-[hash]'
Результат:
dist/
└── js/
└── index-A3F7K2.js
Во время сборки Esbuild заменяет плейсхолдеры реальными значениями.
[name]Плейсхолдер [name] подставляет имя файла без
расширения.
Исходный файл:
src/main.js
Конфигурация:
entryNames: '[name]'
Результат:
main.js
Другой пример:
src/admin.js
Результат:
admin.js
entryNames: 'pages/[name]'
Результат:
dist/
└── pages/
└── main.js
[hash][hash] добавляет уникальный хеш содержимого файла.
entryNames: '[name]-[hash]'
Результат:
index-R4JK9Q.js
После изменения кода:
index-B72FKM.js
Основное назначение — управление кэшированием браузера.
Без хеша:
app.js
После обновления приложения имя остаётся прежним:
app.js
Браузер может использовать старую закэшированную версию.
С хешем:
app-W3J4K8.js
После изменения:
app-X8N2L1.js
Поскольку имя файла изменилось, браузер гарантированно загрузит новую версию.
Такой подход называется cache busting.
[dir][dir] сохраняет структуру каталогов относительно базовой
директории.
Рассмотрим проект:
src/
├── admin/
│ └── index.js
└── user/
└── index.js
Конфигурация:
entryNames: '[dir]/[name]'
Результат:
dist/
├── admin/
│ └── index.js
└── user/
└── index.js
Без использования [dir] возник бы конфликт:
dist/
└── index.js
Поскольку оба файла имеют одинаковое имя.
Плейсхолдеры можно комбинировать.
Пример:
entryNames: '[dir]/[name]-[hash]'
Результат:
dist/
├── admin/
│ └── index-T6A9K2.js
└── user/
└── index-P9F4D7.js
Часто требуется размещать итоговые файлы в отдельных папках.
entryNames: 'assets/js/[name]'
Результат:
dist/
└── assets/
└── js/
└── main.js
entryNames: 'assets/js/[name]-[hash]'
Результат:
dist/
└── assets/
└── js/
└── main-X8K2L9.js
Исходные данные:
entryPoints: [
'src/home.js',
'src/about.js',
'src/contact.js'
]
Конфигурация:
entryNames: '[name]-bundle'
Результат:
home-bundle.js
about-bundle.js
contact-bundle.js
Каждая точка входа получает собственное имя согласно шаблону.
Структура проекта:
src/
├── pages/
│ ├── home.js
│ ├── blog.js
│ └── contacts.js
Конфигурация:
await esbuild.build({
entryPoints: [
'src/pages/home.js',
'src/pages/blog.js',
'src/pages/contacts.js'
],
bundle: true,
outdir: 'dist',
entryNames: 'pages/[name]-[hash]'
});
Результат:
dist/
└── pages/
├── home-AB123C.js
├── blog-FF821D.js
└── contacts-91AD11.js
Подобная схема часто используется в production-сборках.
Важно понимать различие между:
entryNameschunkNamesentryNames влияет только на файлы, являющиеся точками
входа.
Например:
entryPoints: ['src/index.js']
Файл:
import('./module.js');
Если включено разделение кода:
splitting: true
то динамически загружаемые модули будут использовать настройки
chunkNames, а не entryNames.
Пример:
entryNames: '[name]-[hash]',
chunkNames: 'chunks/[name]-[hash]'
Результат:
dist/
├── index-D81F3A.js
└── chunks/
└── chunk-M9L1K2.js
Если из точки входа генерируется отдельный CSS-файл:
import './styles.css';
Esbuild создаёт CSS-ресурс, связанный с соответствующим entry-файлом.
Конфигурация:
entryNames: '[name]-[hash]'
Результат:
dist/
├── app-F3K1Q8.js
└── app-F3K1Q8.css
Одинаковый хеш позволяет легко связывать ресурсы между собой.
outbaseПлейсхолдер [dir] особенно полезен в сочетании с
параметром outbase.
Структура:
src/
├── admin/index.js
└── shop/index.js
Конфигурация:
await esbuild.build({
entryPoints: [
'src/admin/index.js',
'src/shop/index.js'
],
outbase: 'src',
outdir: 'dist',
bundle: true,
entryNames: '[dir]/[name]'
});
Результат:
dist/
├── admin/
│ └── index.js
└── shop/
└── index.js
outbase определяет точку отсчёта для вычисления значения
[dir].
entryNames: '[name]'
Результат:
main.js
entryNames: '[name]-[hash]'
Результат:
main-A8D2F4.js
entryNames: 'assets/[name]-[hash]'
Результат:
assets/main-A8D2F4.js
entryNames: '[dir]/[name]'
Результат:
admin/index.js
user/index.js
entryNames: '[dir]/[name]-[hash]'
Результат:
admin/index-A8D2F4.js
user/index-C9L7P1.js
Во время разработки важны простота и предсказуемость.
Часто используется:
entryNames: '[name]'
или
entryNames: '[dir]/[name]'
Это облегчает поиск файлов и отладку.
Для производственных сборок почти всегда применяется хеширование:
entryNames: '[name]-[hash]'
или
entryNames: 'assets/js/[name]-[hash]'
Так обеспечивается корректное обновление ресурсов после деплоя.
Для больших проектов характерна вложенная структура каталогов:
entryNames: '[dir]/[name]-[hash]'
Такой подход:
Опция entryNames работает только для точек входа.
Не влияет на:
assetNames;Для полной настройки структуры сборки обычно совместно используются:
entryNames
chunkNames
assetNames
Пример комплексной конфигурации:
await esbuild.build({
entryPoints: ['src/index.js'],
bundle: true,
splitting: true,
format: 'esm',
outdir: 'dist',
entryNames: 'js/[name]-[hash]',
chunkNames: 'chunks/[name]-[hash]',
assetNames: 'assets/[name]-[hash]'
});
Результирующая структура:
dist/
├── js/
│ └── index-AB12CD.js
├── chunks/
│ └── chunk-EF34GH.js
└── assets/
├── logo-XY98ZT.svg
└── font-LM44NP.woff2
Опция entryNames является одним из ключевых инструментов
управления выходной структурой Esbuild. Благодаря поддержке шаблонов
[name], [hash] и [dir] можно
строить как простые схемы именования для разработки, так и сложные
production-конфигурации с сохранением структуры каталогов и эффективным
кэшированием ресурсов.