Опция outfile и outdir

При сборке проектов с помощью Esbuild результат работы компилятора необходимо сохранить в файловой системе. Для управления местом сохранения используются две основные опции:

  • outfile — указывает конкретный файл для итоговой сборки.
  • outdir — задаёт каталог, в который будут помещены один или несколько выходных файлов.

Обе опции относятся к настройке выходных данных (output configuration), однако используются в разных сценариях.


Опция outfile

Параметр outfile определяет точное имя и путь выходного файла.

Пример:

esbuild src/index.js --bundle --outfile=dist/app.js

Исходный файл:

src/
└── index.js

После сборки:

dist/
└── app.js

Esbuild объединяет все зависимости в один файл и сохраняет результат по указанному пути.

Эквивалентная конфигурация через JavaScript API:

const esbuild = require('esbuild');

esbuild.build({
  entryPoints: ['src/index.js'],
  bundle: true,
  outfile: 'dist/app.js'
});

Когда использовать outfile

Опция подходит в следующих ситуациях:

Сборка одного файла

Если приложение содержит единственную точку входа:

esbuild.build({
  entryPoints: ['src/main.js'],
  bundle: true,
  outfile: 'build/main.js'
});

Результатом станет один файл:

build/
└── main.js

Генерация библиотеки

При создании библиотеки часто требуется получить один итоговый файл:

esbuild.build({
  entryPoints: ['src/library.js'],
  bundle: true,
  format: 'esm',
  outfile: 'dist/library.js'
});

Минификация в конкретный файл

esbuild.build({
  entryPoints: ['src/app.js'],
  bundle: true,
  minify: true,
  outfile: 'dist/app.min.js'
});

После сборки:

dist/
└── app.min.js

Ограничения outfile

Главное ограничение заключается в том, что параметр предполагает создание одного выходного файла.

Следующая конфигурация приведёт к ошибке:

esbuild.build({
  entryPoints: [
    'src/admin.js',
    'src/client.js'
  ],
  bundle: true,
  outfile: 'dist/app.js'
});

Причина очевидна: несколько входных файлов невозможно сохранить в один результирующий файл без дополнительной логики разделения.

Для таких случаев применяется outdir.


Опция outdir

Параметр outdir задаёт каталог для сохранения результатов сборки.

Пример:

esbuild src/*.js --bundle --outdir=dist

Структура проекта:

src/
├── admin.js
├── client.js
└── dashboard.js

После выполнения:

dist/
├── admin.js
├── client.js
└── dashboard.js

Каждая точка входа получает собственный выходной файл.


Использование outdir через JavaScript API

const esbuild = require('esbuild');

esbuild.build({
  entryPoints: [
    'src/admin.js',
    'src/client.js'
  ],
  bundle: true,
  outdir: 'dist'
});

Результат:

dist/
├── admin.js
└── client.js

Автоматическое создание каталога

Если указанный каталог отсутствует, Esbuild создаёт его автоматически.

Конфигурация:

esbuild.build({
  entryPoints: ['src/index.js'],
  bundle: true,
  outdir: 'public/assets/js'
});

Если директории:

public/

не существует, Esbuild создаст весь путь:

public/
└── assets/
    └── js/
        └── index.js

Это избавляет от необходимости предварительно создавать каталоги вручную.


Работа с несколькими точками входа

Наиболее распространённый сценарий использования outdir — сборка нескольких entry points.

Исходная структура:

src/
├── pages/
│   ├── home.js
│   ├── about.js
│   └── contacts.js

Конфигурация:

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

Каждый файл компилируется отдельно.


Использование outdir с Code Splitting

Функция разделения кода требует наличия каталога для сохранения нескольких файлов.

Пример:

esbuild.build({
  entryPoints: [
    'src/app.js',
    'src/admin.js'
  ],
  bundle: true,
  splitting: true,
  format: 'esm',
  outdir: 'dist'
});

Результат может выглядеть следующим образом:

dist/
├── app.js
├── admin.js
└── chunk-XYZ123.js

Появление дополнительных chunk-файлов делает использование outfile невозможным.

Поэтому при включении:

splitting: true

обычно применяется именно:

outdir: 'dist'

Сохранение структуры каталогов

При использовании нескольких входных файлов Esbuild способен сохранять часть исходной структуры директорий.

Исходный проект:

src/
├── admin/
│   └── index.js
└── client/
    └── index.js

Конфигурация:

esbuild.build({
  entryPoints: [
    'src/admin/index.js',
    'src/client/index.js'
  ],
  outdir: 'dist',
  bundle: true
});

По умолчанию результат может выглядеть так:

dist/
├── admin.js
└── client.js

Для более тонкого управления структурой используются дополнительные параметры, такие как outbase, однако основным контейнером для сохранения файлов остаётся именно outdir.


Совместное использование с генерацией ресурсов

При обработке изображений, шрифтов и других ассетов Esbuild часто создаёт дополнительные файлы.

Пример:

esbuild.build({
  entryPoints: ['src/main.js'],
  bundle: true,
  loader: {
    '.png': 'file'
  },
  outdir: 'dist'
});

Если в коде присутствует импорт:

import logo from './logo.png';

После сборки:

dist/
├── main.js
└── logo-ABCD12.png

Поскольку формируется более одного файла, применение outfile становится неудобным или невозможным.


Отличия outfile и outdir

Характеристика outfile outdir
Указывает конкретный файл Да Нет
Указывает каталог Нет Да
Подходит для одной точки входа Да Да
Подходит для нескольких точек входа Нет Да
Поддерживает code splitting Нет Да
Подходит для генерации ассетов Ограниченно Да
Создаёт множество файлов Нет Да

Выбор между outfile и outdir

Использование outfile

Подходит, если:

  • имеется одна точка входа;
  • нужен один итоговый файл;
  • создаётся библиотека;
  • выполняется минификация одного скрипта;
  • отсутствует code splitting.

Пример:

esbuild.build({
  entryPoints: ['src/index.js'],
  bundle: true,
  outfile: 'dist/app.js'
});

Использование outdir

Подходит, если:

  • существует несколько точек входа;
  • используется разделение кода;
  • генерируются дополнительные ресурсы;
  • требуется сохранение нескольких файлов сборки;
  • проект имеет сложную структуру.

Пример:

esbuild.build({
  entryPoints: [
    'src/main.js',
    'src/admin.js'
  ],
  bundle: true,
  splitting: true,
  format: 'esm',
  outdir: 'dist'
});

Типичные ошибки

Одновременное использование outfile и outdir

Некорректная конфигурация:

esbuild.build({
  entryPoints: ['src/index.js'],
  bundle: true,
  outfile: 'dist/app.js',
  outdir: 'dist'
});

Esbuild не позволяет одновременно задавать оба варианта размещения результата, поскольку они решают одну и ту же задачу разными способами.


Использование outfile при нескольких entry points

Ошибочный пример:

esbuild.build({
  entryPoints: [
    'src/home.js',
    'src/about.js'
  ],
  outfile: 'dist/app.js'
});

Следует заменить на:

esbuild.build({
  entryPoints: [
    'src/home.js',
    'src/about.js'
  ],
  outdir: 'dist'
});

Использование outfile с code splitting

Некорректная конфигурация:

esbuild.build({
  entryPoints: ['src/index.js'],
  bundle: true,
  splitting: true,
  format: 'esm',
  outfile: 'dist/app.js'
});

Разделение кода предполагает появление нескольких файлов, поэтому необходимо использовать каталог:

esbuild.build({
  entryPoints: ['src/index.js'],
  bundle: true,
  splitting: true,
  format: 'esm',
  outdir: 'dist'
});

Влияние на архитектуру сборки

Опция outfile ориентирована на сценарий «один вход — один результат». Она обеспечивает максимально простой процесс сборки и удобна для небольших приложений, библиотек и утилит.

Опция outdir ориентирована на современные многостраничные приложения, крупные фронтенд-проекты, системы с разделением кода и обработкой статических ресурсов. Практически все сложные конфигурации Esbuild, связанные с несколькими выходными файлами, строятся вокруг использования выходного каталога, что делает outdir основной опцией для масштабируемых процессов сборки.