Режим serve: встроенный HTTP-сервер

Архитектура режима serve

Режим serve в esbuild предназначен для локальной разработки и представляет собой встроенный HTTP-сервер, который совмещает две ключевые функции: сборку проекта и раздачу результата через веб-интерфейс.

В отличие от классического подхода «сначала сборка в папку — затем запуск отдельного сервера», здесь процесс объединён в один шаг. esbuild запускает сервер, который:

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

Ключевая особенность заключается в том, что сервер интегрирован непосредственно в процесс сборки, а не является внешним инструментом.


Базовый API и структура вызова

Функция serve предоставляется основным API esbuild и имеет следующий общий вид:

import * as esbuild from 'esbuild';

await esbuild.serve(
  {
    port: 3000,
    servedir: 'public'
  },
  {
    entryPoints: ['src/index.js'],
    bundle: true,
    outdir: 'dist'
  }
);

Первый аргумент описывает поведение HTTP-сервера, второй — параметры сборки.

Серверные опции

  • port — порт, на котором запускается сервер.
  • host — адрес привязки (по умолчанию localhost).
  • servedir — директория для статических файлов.

Опции сборки

Во втором аргументе используются стандартные настройки esbuild:

  • entryPoints — точки входа;
  • bundle — объединение модулей;
  • outdir — директория вывода;
  • format — формат модуля (esm, cjs и т.д.);
  • sourcemap — генерация source map.

Принцип работы встроенного сервера

Механизм serve не является полноценным продакшен-сервером. Он оптимизирован под разработку и работает по следующей логике:

  1. При запуске выполняется первичная сборка проекта.

  2. Сервер начинает слушать указанный порт.

  3. При HTTP-запросе:

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

Важно, что esbuild не внедряет полноценный middleware-слой и не предоставляет маршрутизацию уровня Express.


Разделение статических и собранных ресурсов

servedir играет ключевую роль в архитектуре serve-режима. Он определяет, какие файлы считаются статическими.

Типичная структура проекта:

project/
 ├─ public/
 │   ├─ index.html
 │   └─ assets/
 ├─ src/
 │   └─ index.js

В этом случае:

  • public/index.html отдаётся напрямую HTTP-сервером;
  • src/index.js обрабатывается через esbuild;
  • результат сборки подставляется в ответ.

Поведение при изменениях кода

Serve-режим тесно связан с инкрементальной сборкой. esbuild не пересобирает весь проект с нуля при каждом изменении. Вместо этого используется внутренний механизм кэширования:

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

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


Встроенный HTTP-сервер: особенности реализации

HTTP-сервер esbuild реализован на уровне Go runtime, что даёт несколько особенностей:

  • высокая производительность обработки запросов;
  • отсутствие зависимости от Node.js HTTP API;
  • минимальная конфигурация;
  • ограниченный набор функций по сравнению с полноценными фреймворками.

Сервер не предоставляет:

  • роутинг уровня приложения;
  • поддержку middleware;
  • cookie/session management;
  • WebSocket-интерфейсы.

Его задача ограничена обслуживанием сборки и статических файлов.


Кэширование и ускорение ответов

В режиме serve активно используется кэш:

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

Такой подход исключает необходимость записи на диск, что уменьшает I/O-нагрузку.


Поведение при параллельных запросах

Если несколько запросов приходят одновременно:

  • esbuild синхронизирует процесс сборки;
  • параллельные запросы ожидают завершения текущей операции;
  • результат кэшируется и переиспользуется.

Это предотвращает дублирование работы и снижает нагрузку на CPU.


Ограничения режима serve

Несмотря на удобство, режим имеет ряд архитектурных ограничений:

  • отсутствует production-оптимизация серверной логики;
  • нет поддержки сложных маршрутов;
  • отсутствует контроль над HTTP-заголовками;
  • нет встроенной системы hot module replacement (HMR в классическом смысле);
  • ограниченные возможности кастомизации ответа сервера.

Serve предназначен исключительно для разработки и проверки сборки.


Поведение с HTML и точками входа

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

  • ручное подключение скриптов;
  • использование шаблонов;
  • внешние плагины.

Пример связки:

<!-- public/index.html -->
<!doctype html>
<html>
  <head>
    <meta charset="UTF-8">
    <script src="/dist/index.js"></script>
  </head>
  <body>
  </body>
</html>

Интеграция с watch-режимом

Хотя serve и не является заменой watch, он включает аналогичный механизм:

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

В отличие от esbuild.build({ watch: true }), здесь нет необходимости отдельно поднимать HTTP-сервер.


Обработка ошибок сборки

Если в процессе сборки возникает ошибка:

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

Это позволяет не прерывать сессию разработки.


Использование путей и base URL

Serve-режим не изменяет логику путей внутри приложения, но требует корректной настройки:

  • относительные пути зависят от структуры outdir;
  • абсолютные пути обслуживаются через HTTP-сервер;
  • servedir определяет корень статических ресурсов.

При некорректной настройке возможны ситуации, когда HTML загружается, но бандлы не находятся.


Поведение при остановке сервера

Функция serve возвращает объект управления:

const server = await esbuild.serve(options, buildOptions);

// остановка
server.stop();

При остановке:

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

Отличие serve от dev-серверов экосистемы

Serve-режим esbuild отличается от типичных dev-серверов (Vite, Webpack Dev Server):

  • отсутствует плагинная система уровня middleware;
  • минимальный слой абстракции;
  • отсутствие виртуального файлового графа в пользовательском API;
  • более низкий уровень контроля, но выше производительность сборки.

Поведение при изменении конфигурации

Любое изменение параметров сборки требует перезапуска сервера:

  • изменение entryPoints не применяется динамически;
  • изменение outdir требует нового запуска;
  • изменение плагинов также фиксируется только при старте.

Serve не предназначен для динамической реконфигурации во время работы.


Сценарии использования внутри разработки

Serve-режим используется в ситуациях, где требуется:

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

Он особенно эффективен в проектах, где esbuild используется как основной bundler без дополнительного dev-слоя.