В современных приложениях процесс сборки редко ограничивается одним входным файлом. В рамках одного проекта могут существовать отдельные страницы сайта, независимые модули, административные панели, виджеты, сервисные скрипты, Web Workers и серверные части приложения. Для подобных сценариев Esbuild предоставляет поддержку нескольких точек входа (Multiple Entry Points), позволяя собирать сразу множество независимых графов зависимостей за один запуск.
Использование нескольких точек входа позволяет:
Точка входа (entry point) представляет собой исходный файл, с которого начинается построение графа зависимостей.
Простейшая сборка с одной точкой входа:
await esbuild.build({
entryPoints: ['src/index.js'],
bundle: true,
outfile: 'dist/app.js'
});
В данном случае Esbuild начинает анализ с файла
index.js, находит все импорты и формирует единый бандл.
При наличии нескольких независимых приложений количество точек входа увеличивается.
Например:
src/
├── home.js
├── admin.js
└── dashboard.js
Каждый файл представляет отдельное приложение.
Самый простой способ определить несколько точек входа — передать
массив файлов в параметр entryPoints.
await esbuild.build({
entryPoints: [
'src/home.js',
'src/admin.js',
'src/dashboard.js'
],
bundle: true,
outdir: 'dist'
});
После сборки:
dist/
├── home.js
├── admin.js
└── dashboard.js
Каждый файл получает собственный результирующий бандл.
Esbuild автоматически использует имя исходного файла для имени выходного файла.
При одной точке входа обычно применяется параметр
outfile.
outfile: 'dist/app.js'
При нескольких точках входа необходимо использовать
outdir.
await esbuild.build({
entryPoints: [
'src/home.js',
'src/admin.js'
],
bundle: true,
outdir: 'dist'
});
Неверная конфигурация:
await esbuild.build({
entryPoints: [
'src/home.js',
'src/admin.js'
],
bundle: true,
outfile: 'dist/app.js'
});
В таком случае Esbuild выдаст ошибку, поскольку несколько входных файлов невозможно записать в один выходной файл.
Один из наиболее распространённых сценариев — многостраничный сайт.
Структура проекта:
src/
├── pages/
│ ├── home.js
│ ├── about.js
│ └── contacts.js
└── shared/
├── api.js
└── utils.js
Конфигурация:
await esbuild.build({
entryPoints: [
'src/pages/home.js',
'src/pages/about.js',
'src/pages/contacts.js'
],
bundle: true,
outdir: 'dist'
});
Результат:
dist/
├── home.js
├── about.js
└── contacts.js
Каждая страница получает собственный JavaScript-файл.
Помимо массива путей Esbuild позволяет использовать объект.
await esbuild.build({
entryPoints: {
home: 'src/home.js',
admin: 'src/admin.js',
dashboard: 'src/dashboard.js'
},
bundle: true,
outdir: 'dist'
});
Результат:
dist/
├── home.js
├── admin.js
└── dashboard.js
Такой подход полезен, когда требуется явно контролировать имена выходных файлов.
Параметр entryNames позволяет управлять схемой
именования результатов сборки.
Пример:
await esbuild.build({
entryPoints: [
'src/home.js',
'src/admin.js'
],
bundle: true,
outdir: 'dist',
entryNames: '[name]-bundle'
});
Результат:
dist/
├── home-bundle.js
└── admin-bundle.js
Поддерживаются шаблоны:
| Шаблон | Назначение |
|---|---|
[name] |
Имя входного файла |
[dir] |
Исходная директория |
[hash] |
Контрольная сумма |
[ext] |
Расширение |
При работе с большим количеством страниц важно сохранять исходную структуру каталогов.
Исходная структура:
src/
├── public/
│ ├── home.js
│ └── about.js
└── admin/
└── dashboard.js
Конфигурация:
await esbuild.build({
entryPoints: [
'src/public/home.js',
'src/public/about.js',
'src/admin/dashboard.js'
],
bundle: true,
outdir: 'dist',
entryNames: '[dir]/[name]'
});
Результат:
dist/
├── public/
│ ├── home.js
│ └── about.js
└── admin/
└── dashboard.js
Подобный подход особенно удобен в крупных приложениях с десятками страниц.
Рассмотрим структуру:
src/
├── home.js
├── admin.js
└── utils.js
Файл home.js:
import { formatDate } from './utils.js';
Файл admin.js:
import { formatDate } from './utils.js';
Без дополнительной настройки содержимое utils.js будет
включено в оба бандла.
Схематически:
home.js
└─ utils.js
admin.js
└─ utils.js
Это приводит к дублированию кода.
Для устранения дублирования используется механизм code splitting.
await esbuild.build({
entryPoints: [
'src/home.js',
'src/admin.js'
],
bundle: true,
splitting: true,
format: 'esm',
outdir: 'dist'
});
Результат:
dist/
├── home.js
├── admin.js
└── chunk-XYZ.js
Общий код переносится в отдельный chunk.
Преимущества:
Файл:
const module = await import('./analytics.js');
При включённом разделении кода:
await esbuild.build({
entryPoints: [
'src/home.js',
'src/admin.js'
],
bundle: true,
splitting: true,
format: 'esm',
outdir: 'dist'
});
Esbuild создаёт дополнительные чанки:
dist/
├── home.js
├── admin.js
├── analytics-ABC.js
└── chunk-XYZ.js
Загрузка таких файлов происходит только по мере необходимости.
В крупных проектах количество страниц может исчисляться десятками или сотнями.
Вместо ручного перечисления файлов часто используется автоматическое формирование списка точек входа.
Например, через Node.js:
import { glob } from 'glob';
const entryPoints = await glob('src/pages/**/*.js');
await esbuild.build({
entryPoints,
bundle: true,
outdir: 'dist'
});
При добавлении новой страницы конфигурация остаётся неизменной.
Один запуск Esbuild может обрабатывать сразу несколько независимых приложений.
Структура:
src/
├── client.js
├── admin.js
└── worker.js
Конфигурация:
await esbuild.build({
entryPoints: [
'src/client.js',
'src/admin.js',
'src/worker.js'
],
bundle: true,
outdir: 'dist'
});
Результат:
dist/
├── client.js
├── admin.js
└── worker.js
Каждый файл имеет собственный набор зависимостей.
Web Worker часто рассматривается как отдельная точка входа.
Структура:
src/
├── main.js
└── worker.js
Конфигурация:
await esbuild.build({
entryPoints: [
'src/main.js',
'src/worker.js'
],
bundle: true,
outdir: 'dist'
});
Использование:
const worker = new Worker('/worker.js', {
type: 'module'
});
Основное приложение и Worker собираются независимо.
Один проект может содержать:
src/
├── website/
│ ├── home.js
│ └── about.js
├── admin/
│ └── panel.js
├── widgets/
│ ├── chat.js
│ └── feedback.js
└── worker.js
Конфигурация:
await esbuild.build({
entryPoints: [
'src/website/home.js',
'src/website/about.js',
'src/admin/panel.js',
'src/widgets/chat.js',
'src/widgets/feedback.js',
'src/worker.js'
],
bundle: true,
splitting: true,
format: 'esm',
outdir: 'dist'
});
Esbuild построит общий граф зависимостей, вынесет повторяющийся код в чанки и сформирует набор оптимизированных файлов.
Во время разработки особенно важна скорость пересборки.
Пример:
const context = await esbuild.context({
entryPoints: [
'src/home.js',
'src/admin.js',
'src/dashboard.js'
],
bundle: true,
outdir: 'dist'
});
await context.watch();
После изменения файлов Esbuild пересобирает только необходимые части графа зависимостей.
Даже при десятках точек входа скорость остаётся значительно выше по сравнению со многими традиционными сборщиками.
Для изучения структуры зависимостей удобно использовать метафайл.
await esbuild.build({
entryPoints: [
'src/home.js',
'src/admin.js'
],
bundle: true,
metafile: true,
outdir: 'dist'
});
Полученный объект содержит информацию:
Это особенно полезно при работе с большим количеством точек входа.
Использование нескольких точек входа оправдано, когда:
Для максимальной эффективности рекомендуется:
outdir вместо outfile;splitting: true при наличии общих
зависимостей;esm;[dir];Механизм нескольких точек входа является одной из ключевых возможностей Esbuild при построении сложных приложений, позволяя объединять множество независимых сборок в единый высокопроизводительный процесс без усложнения конфигурации.