Типичный проект, использующий esbuild, строится вокруг минималистичного подхода к сборке, где основная логика отделена от конфигурации, а структура каталогов подчинена принципу предсказуемости и скорости обработки исходного кода.
Основная идея организации проекта заключается в том, что исходный код располагается отдельно от артефактов сборки, а сама сборка выполняется либо через CLI-команды, либо через программный API esbuild. Это формирует устойчивый шаблон структуры, который легко масштабируется от небольших библиотек до полноценных фронтенд-приложений.
Наиболее распространённый вариант структуры проекта выглядит следующим образом:
project/
src/
index.js
app.js
components/
utils/
dist/
build/
public/
package.json
esbuild.config.js
Каталог src является центральной частью проекта. В нём
хранится весь исходный JavaScript/TypeScript код до трансформации:
index.js или main.js — точка входаcomponents/ — переиспользуемые модули интерфейсаutils/ — вспомогательные функцииservices/ — логика взаимодействия с APIstyles/ (если CSS обрабатывается через
esbuild-плагины)В случае использования TypeScript структура расширяется файлами
.ts и .tsx, при этом esbuild обрабатывает их
напрямую без необходимости предварительной компиляции через tsc.
Каталог dist используется как выходной для собранных
файлов:
dist/bundle.jsdist/bundle.css (если CSS включён в сборку)dist/assets/*Особенность esbuild заключается в том, что этот каталог часто полностью пересоздаётся при каждой сборке. Инкрементальная логика реализуется внутри процесса, а не через сохранение артефактов на диске.
Каталог public содержит ресурсы, которые не проходят
через сборку:
index.html)При использовании dev-серверов этот каталог часто копируется в
dist без изменений.
Несмотря на то, что esbuild можно использовать напрямую из CLI, в большинстве проектов создаётся файл конфигурации:
esbuild.config.js
Пример базовой конфигурации:
const esbuild = require("esbuild");
esbuild.build({
entryPoints: ["src/index.js"],
bundle: true,
outdir: "dist",
minify: true,
sourcemap: true,
target: "es2018"
});
Конфигурация обычно не становится монолитной — вместо этого она разделяется на логические блоки:
В типичном проекте выделяются два режима:
Характерные параметры:
Пример:
esbuild.context({
entryPoints: ["src/index.js"],
bundle: true,
outdir: "dist",
sourcemap: true
}).then(ctx => ctx.watch());
Характерные параметры:
esbuild.build({
entryPoints: ["src/index.js"],
bundle: true,
outdir: "dist",
minify: true,
splitting: true,
format: "esm"
});
Для проектов с несколькими точками входа структура расширяется:
src/
pages/
home.js
about.js
dashboard.js
Конфигурация:
esbuild.build({
entryPoints: [
"src/pages/home.js",
"src/pages/about.js",
"src/pages/dashboard.js"
],
bundle: true,
outdir: "dist",
splitting: true,
format: "esm"
});
В результате dist содержит несколько независимых
бандлов, а также общие чанки при включённом code splitting.
При использовании TypeScript структура практически не меняется, но добавляется файл:
tsconfig.json
При этом esbuild:
tsc --noEmit для проверки
типов (при необходимости)Типичная структура:
src/
index.ts
types/
modules/
Проекты с esbuild часто используют плагины для расширения функциональности:
Структура проекта при этом может включать:
build/
plugins/
css-plugin.js
alias-plugin.js
Пример подключения:
const cssPlugin = require("./build/plugins/css-plugin");
esbuild.build({
entryPoints: ["src/index.js"],
bundle: true,
outdir: "dist",
plugins: [cssPlugin]
});
Для крупных проектов используется логическая группировка модулей:
src/
ui/
core/
api/
state/
config/
Часто добавляются алиасы:
alias({
"@ui": "./src/ui",
"@core": "./src/core"
});
Это влияет на структуру импортов:
import Button from "@ui/Button";
import request from "@core/request";
При разработке структура проекта дополняется временными механизмами:
Иногда добавляется файл:
dev.js
const esbuild = require("esbuild");
esbuild.context({
entryPoints: ["src/index.js"],
bundle: true,
outdir: "dist",
sourcemap: true
}).then(ctx => {
ctx.watch();
ctx.serve({ port: 3000 });
});
В монорепозиториях структура меняется:
packages/
app/
ui/
shared/
tools/
build/
Каждый пакет может иметь собственный esbuild-конфиг или общий конфиг
уровня tools/build.
Особенность esbuild в таких структурах — возможность быстро пересобирать отдельные пакеты без глобального пересчёта всего графа зависимостей.
Файл package.json играет ключевую роль:
{
"scripts": {
"build": "node esbuild.config.js",
"dev": "node dev.js"
}
}
Типичная структура зависимостей:
esbuild — основной инструментВ больших проектах конфигурация esbuild часто разбивается:
build/
base.js
dev.js
prod.js
shared.js
Пример:
// base.js
module.exports = {
entryPoints: ["src/index.js"],
bundle: true
};
// prod.js
const base = require("./base");
module.exports = {
...base,
outdir: "dist",
minify: true
};
esbuild поддерживает разные форматы:
iife — для браузеров без модулейesm — современный стандартcjs — Node.js окружениеЭто влияет на структуру dist:
dist/
app.js
app.esm.js
app.cjs.js
При мультиформатной сборке проект становится более универсальным для различных сред выполнения.
При обработке CSS и статических файлов структура расширяется:
src/
styles/
main.css
assets/
logo.svg
Выход:
dist/
main.css
assets/
logo.hash.svg
esbuild может либо встраивать ассеты, либо выносить их отдельно, в зависимости от конфигурации loader’ов.
Структура проекта вокруг esbuild обычно строится на трёх принципах:
Такой подход позволяет сохранять предсказуемость структуры даже при росте количества модулей, точек входа и типов выходных артефактов.