Esbuild — это современный инструмент для сборки (bundling) и трансформации JavaScript и TypeScript-кода, созданный Эваном Уоллесом. Основная особенность Esbuild заключается в исключительной производительности: большинство операций выполняется в десятки и даже сотни раз быстрее по сравнению с традиционными инструментами сборки.
Esbuild написан на языке Go и компилируется в нативный исполняемый файл, благодаря чему достигается высокая скорость обработки проектов любого размера.
Основные возможности Esbuild:
До появления Esbuild основными инструментами сборки были:
Несмотря на широкое распространение, все они имели общий недостаток — сравнительно низкую скорость работы на крупных проектах.
Например, сборка проекта через Webpack может занимать десятки секунд или даже минуты. Esbuild выполняет аналогичные задачи за доли секунды благодаря:
Внутри Esbuild можно условно выделить несколько компонентов:
Считывает исходный код:
import { sum } from './math.js';
console.log(sum(10, 20));
и преобразует его в AST (Abstract Syntax Tree).
После построения AST Esbuild находит все импортируемые модули:
import React from 'react';
import App from './App';
Формируется граф зависимостей проекта.
На этом этапе выполняется:
Финальная стадия включает:
npm install esbuild --save-dev
yarn add esbuild --dev
pnpm add esbuild -D
npx esbuild --version
Пример вывода:
0.25.0
Структура проекта:
project/
├── src/
│ └── index.js
└── package.json
Файл:
// src/index.js
console.log('Hello Esbuild');
Сборка:
npx esbuild src/index.js --bundle --outfile=dist/bundle.js
После выполнения команды:
dist/
└── bundle.js
Включает режим объединения модулей.
npx esbuild src/index.js --bundle --outfile=dist/app.js
Указывает итоговый файл.
--outfile=dist/main.js
Используется для вывода нескольких файлов.
--outdir=dist
Минификация кода.
npx esbuild src/index.js --bundle --minify --outfile=dist/app.js
Исходный код:
function sayHello(name) {
console.log('Hello', name);
}
После минификации:
function o(l){console.log("Hello",l)}
Создание source maps.
npx esbuild src/index.js \
--bundle \
--sourcemap \
--outfile=dist/app.js
Автоматическая пересборка.
npx esbuild src/index.js \
--bundle \
--watch \
--outfile=dist/app.js
Определяет целевую платформу.
--target=es2020
Другие варианты:
es2015
es2016
es2017
es2018
es2019
es2020
es2021
es2022
esnext
CLI подходит для простых задач, но реальные проекты обычно используют программный API.
const esbuild = require('esbuild');
esbuild.build({
entryPoints: ['src/index.js'],
bundle: true,
outfile: 'dist/bundle.js'
});
const esbuild = require('esbuild');
async function build() {
await esbuild.build({
entryPoints: ['src/index.js'],
bundle: true,
outfile: 'dist/bundle.js'
});
}
build();
const esbuild = require('esbuild');
esbuild.build({
entryPoints: ['src/index.js'],
bundle: true,
outfile: 'dist/bundle.js'
}).catch(() => process.exit(1));
Одно из главных преимуществ Esbuild — встроенная поддержка TypeScript.
Установка TypeScript необязательна для простой компиляции.
Файл:
interface User {
id: number;
name: string;
}
const user: User = {
id: 1,
name: 'Alex'
};
console.log(user);
Сборка:
npx esbuild src/index.ts \
--bundle \
--outfile=dist/app.js
Esbuild выполняет:
Но не выполняет полноценную проверку типов.
Например:
let age: number = "25";
Esbuild успешно соберёт файл.
Для проверки типов рекомендуется отдельно запускать:
tsc --noEmit
Типичная схема:
{
"scripts": {
"typecheck": "tsc --noEmit",
"build": "esbuild src/index.ts --bundle --outfile=dist/app.js"
}
}
Esbuild умеет компилировать JSX без дополнительных загрузчиков.
Пример:
function App() {
return <h1>Hello React</h1>;
}
Сборка:
npx esbuild src/index.jsx \
--bundle \
--outfile=dist/app.js
Установка:
npm install react react-dom
import ReactDOM from 'react-dom/client';
import App from './App';
const root = ReactDOM.createRoot(
document.getElementById('root')
);
root.render(<App />);
npx esbuild src/index.jsx \
--bundle \
--outfile=dist/app.js
npx esbuild src/index.jsx \
--bundle \
--jsx=automatic \
--outfile=dist/app.js
Tree Shaking — удаление неиспользуемого кода.
Файл:
export function used() {
return 'used';
}
export function unused() {
return 'unused';
}
Использование:
import { used } from './utils';
console.log(used());
После сборки функция unused() будет удалена.
Преимущества:
Позволяет разбивать приложение на отдельные чанки.
Пример:
const module = await import('./heavy-module');
Сборка:
npx esbuild src/index.js \
--bundle \
--splitting \
--format=esm \
--outdir=dist
Результат:
dist/
├── index.js
├── chunk-ABC123.js
└── chunk-XYZ456.js
Esbuild поддерживает три вида оптимизации:
const a = 1;
const b = 2;
↓
const a=1,b=2;
// Comment
const value = 10;
↓
const value=10;
function calculateTotalPrice() {}
↓
function a(){}
Source Maps связывают итоговый бандл с исходным кодом.
Команда:
npx esbuild src/index.js \
--bundle \
--sourcemap \
--outfile=dist/app.js
Результат:
dist/
├── app.js
└── app.js.map
В браузере разработчик будет видеть оригинальные файлы вместо минифицированного кода.
Esbuild умеет обрабатывать CSS.
Файл:
body {
margin: 0;
}
Импорт:
import './styles.css';
Сборка:
npx esbuild src/index.js \
--bundle \
--outfile=dist/app.js
Результат:
dist/
├── app.js
└── app.css
Esbuild содержит простой dev server.
Пример:
const esbuild = require('esbuild');
esbuild.serve({
servedir: 'public'
}, {
entryPoints: ['src/index.js'],
bundle: true,
outfile: 'public/app.js'
});
Сервер автоматически запускается локально.
Позволяет отслеживать изменения файлов.
const esbuild = require('esbuild');
const ctx = await esbuild.context({
entryPoints: ['src/index.js'],
bundle: true,
outfile: 'dist/app.js'
});
await ctx.watch();
После сохранения любого файла выполняется пересборка.
Esbuild поддерживает несколько платформ.
{
platform: 'browser'
}
Оптимизация под браузеры.
{
platform: 'node'
}
Корректно обрабатываются встроенные модули Node.js:
import fs from 'fs';
{
platform: 'neutral'
}
Используется для библиотек и универсального кода.
{
format: 'iife'
}
Подходит для подключения через <script>.
{
format: 'cjs'
}
Используется в Node.js.
{
format: 'esm'
}
Современный стандарт JavaScript-модулей.
Плагин представляет собой объект с методом setup.
Пример:
const examplePlugin = {
name: 'example',
setup(build) {
build.onResolve({ filter: /.*/ }, args => {
console.log(args.path);
return null;
});
}
};
Подключение:
await esbuild.build({
entryPoints: ['src/index.js'],
bundle: true,
plugins: [examplePlugin],
outfile: 'dist/app.js'
});
Основные хуки:
build.onStart(...)
build.onResolve(...)
build.onLoad(...)
build.onEnd(...)
build.onDispose(...)
Схема работы:
onStart
↓
onResolve
↓
onLoad
↓
Сборка
↓
onEnd
Пример виртуального файла:
const virtualPlugin = {
name: 'virtual',
setup(build) {
build.onResolve(
{ filter: /^virtual$/ },
() => ({
path: 'virtual',
namespace: 'virtual'
})
);
build.onLoad(
{
filter: /.*/,
namespace: 'virtual'
},
() => ({
contents: `
export const version = "1.0.0";
`,
loader: 'js'
})
);
}
};
Использование:
import { version } from 'virtual';
Типичные показатели:
| Инструмент | Время сборки |
|---|---|
| Webpack | 20–60 сек |
| Rollup | 5–20 сек |
| Parcel | 5–15 сек |
| Esbuild | менее 1 сек |
Конкретные результаты зависят от:
Несмотря на высокую скорость, Esbuild имеет ряд ограничений.
Необходимо запускать:
tsc --noEmit
отдельно.
По сравнению с Webpack количество плагинов существенно меньше.
Некоторые сложные сценарии легче реализовать через Webpack или Vite.
Многие разработчики считают Vite конкурентом Esbuild, однако это разные инструменты.
Vite использует Esbuild для:
При этом финальная production-сборка обычно выполняется через Rollup.
Схема:
Vite
├─ Dev Server
├─ HMR
├─ Конфигурация
└─ Esbuild
↓
Быстрые преобразования
Для современных проектов рекомендуется следующая схема:
{
"scripts": {
"dev": "node build-dev.js",
"build": "node build-prod.js",
"typecheck": "tsc --noEmit"
}
}
Где:
Esbuild особенно эффективен в следующих случаях:
Стоит рассмотреть альтернативы, если необходимы:
Esbuild стал одним из самых значимых инструментов современной JavaScript-экосистемы благодаря сочетанию высокой скорости и простоты использования. Он предоставляет полный набор возможностей для сборки JavaScript, TypeScript, JSX и CSS, поддерживает минификацию, tree shaking, code splitting и создание source maps, при этом оставаясь значительно быстрее большинства конкурентов.
Для большинства современных проектов Esbuild способен полностью заменить классические сборщики или стать основой более сложных инструментов разработки, таких как Vite. Именно поэтому понимание принципов работы Esbuild, его API, системы плагинов и механизмов оптимизации является важным навыком для любого современного JavaScript-разработчика.