Налаштування бандлера esbuild для веб-проекту
esbuild написаний на Go і працює в 10–100 разів швидше аналогів на JavaScript. Холодний старт, який Webpack витрачає 30 секунд, esbuild завершає за 300 мс. Це змінює не тільки час очікування, але й підхід до розробки: перебудування при кожному збереженні перестає бути проблемою.
Де esbuild застосовується напрямку
Більшість проектів використовують esbuild опосередковано — через Vite, який використовує його для dev-сервера, або через Jest з esbuild-jest. Прямое використання виправдано коли:
- потрібен мінімалістичний пайплайн без фреймворкового overheadu
- збирається сервер на Node.js (бандлінг Lambda-функцій, CLI-утиліт)
- існуючий білд занадто повільний і потрібна точкова заміна трансплілятора
- проект в монорепо потребує кастомного скрипту побудови
Встановлення та перший запуск
npm install --save-dev esbuild
Мінімальний запуск без конфіг-файлу:
./node_modules/.bin/esbuild src/index.ts \
--bundle \
--outfile=dist/bundle.js \
--target=es2020 \
--format=esm \
--sourcemap
JavaScript API
esbuild не має YAML/JSON-конфіги — конфігурація через JS API або CLI. JS API дає повний контроль:
// build.mjs
import * as esbuild from 'esbuild';
await esbuild.build({
entryPoints: ['src/index.ts'],
bundle: true,
outdir: 'dist',
format: 'esm',
target: ['es2020', 'chrome90', 'firefox88', 'safari14'],
splitting: true, // code splitting для ESM
sourcemap: true,
minify: process.env.NODE_ENV === 'production',
define: {
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
},
external: ['react', 'react-dom'],
metafile: true, // для аналізу bundle
loader: {
'.png': 'file',
'.svg': 'dataurl',
'.woff2': 'file',
},
});
Dev-сервер з hot reload
esbuild має вбудований dev-сервер та watch-режим:
// dev.mjs
import * as esbuild from 'esbuild';
const ctx = await esbuild.context({
entryPoints: ['src/index.tsx'],
bundle: true,
outdir: 'dist',
format: 'esm',
sourcemap: 'inline',
define: { 'process.env.NODE_ENV': '"development"' },
});
await ctx.watch();
const { host, port } = await ctx.serve({
servedir: 'public', // статика
port: 3000,
});
console.log(`Dev server: http://${host}:${port}`);
Вбудований сервер підтримує SSE для live reload, але не HMR у сенсі React Fast Refresh. Для повноцінного HMR краще використовувати Vite.
Плагіни
Екосистема плагінів значно менша, ніж у Webpack, але ключові завдання закриті:
import { sassPlugin } from 'esbuild-sass-plugin';
import { copy } from 'esbuild-plugin-copy';
await esbuild.build({
plugins: [
sassPlugin({
type: 'css', // або 'css-module' для CSS Modules
}),
copy({
assets: [
{ from: './public/**/*', to: './dist' },
],
}),
],
});
Написати власний плагін нескладно — API простий:
const envPlugin: esbuild.Plugin = {
name: 'env',
setup(build) {
// Перехватуємо імпорти вида `import env from 'env'`
build.onResolve({ filter: /^env$/ }, (args) => ({
path: args.path,
namespace: 'env-ns',
}));
build.onLoad({ filter: /.*/, namespace: 'env-ns' }, () => ({
contents: JSON.stringify(process.env),
loader: 'json',
}));
},
};
Побудова для Node.js
Lambda-функції, CLI-інструменти, серверні скрипти:
await esbuild.build({
entryPoints: ['src/handler.ts'],
bundle: true,
platform: 'node',
target: 'node18',
format: 'cjs', // Lambda очікує CJS
outfile: 'dist/handler.js',
external: [
// AWS SDK не включаємо — він уже в Lambda runtime
'@aws-sdk/*',
// Нативні модулі
'bcrypt',
'sharp',
],
minify: true,
});
Для нативних addon'ів (.node файли) esbuild не справится — потрібний додатковий крок копіювання.
Аналіз метафайлу
const result = await esbuild.build({ ..., metafile: true });
const text = await esbuild.analyzeMetafile(result.metafile!, {
verbose: true,
});
console.log(text);
Або вивантажити в JSON та завантажити на esbuild.github.io/analyze/ — інтерактивна sunburst-діаграма з розмірами модулів.
Обмеження
esbuild навмисне не реалізує ряд речей:
-
TypeScript type checking — esbuild тільки транспілює, не перевіряє типи. Запускайте
tsc --noEmitокремо в CI -
CSS Modules — підтримка базова, немає
composesта кастомних імен класів на кшталт[local]_[hash] - Декоратори — підтримка експериментальна, старий синтаксис декораторів (emitDecoratorMetadata) не підтримується
- Деякі Babel-трансформи — якщо потрібні специфічні трансформи AST, потребується плагін або предобробка через SWC/Babel
Терміни
Заміна трансплілятора в існуючому проекті на esbuild (наприклад, Jest → esbuild-jest): 2–4 години. Настройка повноцінного пайплайну побудови з нуля (dev-сервер, production-побудова, CSS, активи): 4–8 годин.







