Опция serve в Esbuild предназначена для запуска
встроенного HTTP-сервера, который обслуживает файлы проекта и
автоматически пересобирает приложение при изменении исходного кода.
Такой режим особенно полезен во время разработки, когда требуется быстро
получать результаты сборки без настройки стороннего веб-сервера.
В отличие от полноценного dev-сервера современных инструментов вроде Vite или Webpack Dev Server, встроенный сервер Esbuild выполняет ограниченный набор задач:
watch);Основные параметры настройки сервера:
host — сетевой интерфейс, на котором будет запущен
сервер;port — номер TCP-порта;servedir — каталог со статическими файлами.Пример запуска сервера через JavaScript API:
import * as esbuild from 'esbuild';
await esbuild.context({
entryPoints: ['src/index.js'],
bundle: true,
outfile: 'dist/app.js'
}).then(async (ctx) => {
await ctx.serve({
servedir: 'dist',
host: 'localhost',
port: 3000
});
});
После запуска сервер становится доступным по адресу:
http://localhost:3000
Если в каталоге dist присутствует файл
index.html, он будет отдан браузеру при обращении к корню
сайта.
servedirПараметр servedir определяет директорию, содержимое
которой будет доступно через HTTP-сервер.
Пример:
await ctx.serve({
servedir: 'public'
});
Структура проекта:
project/
├── public/
│ ├── index.html
│ ├── styles.css
│ └── images/
│ └── logo.png
└── src/
После запуска будут доступны:
http://localhost:8000/
http://localhost:8000/styles.css
http://localhost:8000/images/logo.png
Наиболее распространённый сценарий — размещение результатов сборки в
каталоге, который одновременно выступает в роли
servedir.
await esbuild.context({
entryPoints: ['src/main.js'],
bundle: true,
outdir: 'dist'
});
await ctx.serve({
servedir: 'dist'
});
Структура после сборки:
dist/
├── index.html
├── main.js
└── main.css
Все файлы автоматически становятся доступными через HTTP.
Иногда статические ресурсы и результаты сборки располагаются в разных местах.
Пример:
project/
├── public/
│ └── index.html
├── dist/
│ └── bundle.js
└── src/
Конфигурация:
await esbuild.context({
entryPoints: ['src/app.js'],
bundle: true,
outfile: 'dist/bundle.js'
});
Если указать:
await ctx.serve({
servedir: 'public'
});
то файл bundle.js окажется недоступен.
Поэтому чаще применяют одну из схем:
public.Например:
outfile: 'public/bundle.js'
index.htmlПри обращении к каталогу сервер пытается найти файл:
index.html
Пример структуры:
dist/
├── index.html
├── about/
│ └── index.html
Тогда адреса будут работать следующим образом:
/
→ dist/index.html
/about/
→ dist/about/index.html
Это позволяет создавать многостраничные приложения без дополнительной конфигурации маршрутизации.
Если файл index.html отсутствует, сервер отображает
список файлов директории.
Например:
dist/
├── app.js
├── styles.css
└── image.png
При открытии:
http://localhost:8000/
будет показан список доступных файлов.
Такое поведение удобно для отладки и быстрого просмотра содержимого каталога сборки.
hostПараметр host определяет сетевой интерфейс, на котором
будет прослушиваться сервер.
Пример:
await ctx.serve({
servedir: 'dist',
host: 'localhost'
});
В этом случае подключения принимаются только локально.
localhostСамый распространённый вариант:
host: 'localhost'
или
host: '127.0.0.1'
Доступ:
http://localhost:8000
Такой режим обеспечивает дополнительную безопасность, поскольку сервер не будет виден другим устройствам сети.
Подходит для:
0.0.0.0Для доступа с других устройств локальной сети используется:
host: '0.0.0.0'
Пример:
await ctx.serve({
servedir: 'dist',
host: '0.0.0.0',
port: 3000
});
После запуска сервер становится доступен по IP-адресу компьютера:
http://192.168.1.15:3000
Теперь страницу можно открыть:
Иногда требуется привязка к определённому интерфейсу.
Пример:
host: '192.168.1.15'
Тогда сервер будет слушать только этот адрес.
Подобный подход применяется при наличии нескольких сетевых интерфейсов:
Ethernet
Wi-Fi
VPN
Docker Network
VirtualBox Adapter
Esbuild поддерживает IPv6-адреса.
Пример:
host: '::1'
Локальное подключение:
http://[::1]:8000
Для всех IPv6-интерфейсов:
host: '::'
Использование:
host: '0.0.0.0'
открывает доступ извне.
Поэтому необходимо учитывать:
Для обычной локальной разработки предпочтительно:
host: 'localhost'
portПараметр port задаёт номер порта, на котором будет
запущен HTTP-сервер.
Пример:
await ctx.serve({
servedir: 'dist',
port: 3000
});
После запуска:
http://localhost:3000
По умолчанию Esbuild пытается подобрать свободный порт автоматически.
Однако явное указание порта делает адрес сервера предсказуемым.
Пример:
port: 8080
Адрес:
http://localhost:8080
Во время разработки часто используются следующие порты:
| Порт | Назначение |
|---|---|
| 3000 | React-приложения |
| 4000 | Вспомогательные сервисы |
| 5000 | API и тестовые серверы |
| 8000 | Значение по умолчанию во многих инструментах |
| 8080 | Альтернатива 80 порту |
Пример:
await ctx.serve({
servedir: 'dist',
port: 8080
});
Если порт уже используется другим процессом:
port: 3000
и на этом адресе уже работает приложение, запуск завершится ошибкой.
Типичная ситуация:
EADDRINUSE
Address already in use
Возможные решения:
Метод serve() возвращает информацию о запущенном
сервере.
Пример:
const result = await ctx.serve({
servedir: 'dist'
});
console.log(result);
Результат может выглядеть так:
{
hosts: ['127.0.0.1'],
port: 8000
}
Это особенно полезно при автоматическом выборе свободного порта.
host, port и
servedirНаиболее типичная конфигурация:
import * as esbuild from 'esbuild';
const ctx = await esbuild.context({
entryPoints: ['src/index.js'],
bundle: true,
outdir: 'dist'
});
await ctx.watch();
const server = await ctx.serve({
servedir: 'dist',
host: 'localhost',
port: 3000
});
console.log(server);
Особенности данной конфигурации:
dist;localhost;3000;watchНа практике serve() почти всегда применяется совместно с
watch().
Пример:
const ctx = await esbuild.context({
entryPoints: ['src/main.js'],
bundle: true,
outdir: 'dist'
});
await ctx.watch();
await ctx.serve({
servedir: 'dist'
});
Последовательность работы:
Таким образом формируется полноценная среда разработки с минимальным количеством настроек и очень высокой скоростью работы.
serveМетод возвращает объект с параметрами работающего сервера.
Пример:
const info = await ctx.serve({
servedir: 'dist',
host: '0.0.0.0',
port: 3000
});
console.log(info);
Результат:
{
hosts: [
'127.0.0.1',
'192.168.1.15'
],
port: 3000
}
Поле hosts содержит адреса, по которым сервер доступен в
текущей системе, а поле port указывает фактически
используемый номер порта.
Эта информация часто применяется для автоматического открытия браузера, вывода адресов в консоль и интеграции с инструментами разработки.