Одна точка входа

Модель сборки с одной точкой входа представляет базовый сценарий работы бандлера: система получает один исходный модуль, от которого строится полный граф зависимостей. Все импортируемые модули рекурсивно подтягиваются, объединяются и трансформируются в один или несколько выходных файлов. В контексте esbuild этот режим является наиболее прямолинейным и используется как отправная точка для большинства проектов.

Принцип формирования графа зависимостей

При указании одной точки входа esbuild выполняет следующие этапы:

  1. Анализирует входной файл как корень графа.
  2. Извлекает все import и require выражения.
  3. Рекурсивно обходит зависимости.
  4. Строит полный граф модулей.
  5. Выполняет трансформацию и объединение кода.

Ключевой момент заключается в том, что исходный файл не рассматривается изолированно — он становится корнем структуры, от которого зависит вся сборка.

Если входной файл выглядит так:

import { formatDate } from "./utils/date.js";
import { createApp } from "./app.js";

createApp();
console.log(formatDate(new Date()));

то esbuild добавляет в граф зависимости ./utils/date.js и ./app.js, а затем их зависимости, если они существуют.

CLI: базовая сборка одной точки входа

В CLI режим одной точки входа задаётся простейшим способом:

esbuild src/index.js --bundle --outfile=dist/bundle.js

Здесь:

  • src/index.js — единственная точка входа;
  • --bundle включает объединение модулей;
  • --outfile задаёт итоговый файл.

В этом режиме esbuild формирует единый файл, содержащий весь код приложения.

Поведение при отсутствии bundle

Если параметр --bundle не указан, esbuild не строит граф зависимостей. В этом случае входной файл просто копируется с минимальными преобразованиями. Это принципиально важно: одна точка входа не означает автоматическую сборку — требуется явное включение бандлинга.

JavaScript API: управление одной точкой входа

В API сценарий с одной точкой входа выглядит следующим образом:

import * as esbuild from "esbuild";

await esbuild.build({
  entryPoints: ["src/index.js"],
  bundle: true,
  outfile: "dist/bundle.js",
});

Здесь entryPoints содержит массив, но фактически используется один элемент. Архитектурно esbuild всегда работает с массивом точек входа, даже если он состоит из одного файла.

Разница между одиночной и множественной конфигурацией

Хотя рассматривается один входной файл, важно понимать внутреннюю универсальность модели:

  • Один entry point → один граф зависимостей → один выходной бандл (в базовой конфигурации)
  • Несколько entry points → несколько независимых графов → несколько бандлов

При этом esbuild не ограничивает один входной файл одним выходным файлом. Возможны альтернативные режимы:

await esbuild.build({
  entryPoints: ["src/index.js"],
  bundle: true,
  outdir: "dist",
});

В этом случае даже при одной точке входа используется режим директории вывода, что становится актуально при дополнительных настройках, таких как splitting или asset loading.

Влияние на tree shaking

Одна точка входа усиливает эффективность удаления неиспользуемого кода. При наличии единого графа зависимостей esbuild может точно определить:

  • какие экспортируемые символы используются;
  • какие модули не достигаются из entry point;
  • какие побочные эффекты отсутствуют.

Пример:

// utils.js
export function used() {
  return "used";
}

export function unused() {
  return "unused";
}

// index.js
import { used } from "./utils.js";

console.log(used());

Функция unused будет удалена на этапе tree shaking, так как не попадает в достижимый граф.

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

Сценарий с одной точкой входа часто соответствует следующим архитектурным моделям:

SPA (Single Page Application)

Один файл инициализации:

import { initRouter } from "./router.js";
import { initStore } from "./store.js";

initStore();
initRouter();

Вся система стартует из единой точки, что делает модель естественной для esbuild.

Библиотеки

При сборке библиотеки часто используется один entry point, который агрегирует публичный API:

export { createClient } from "./client.js";
export { parseConfig } from "./config.js";

Управление выходным файлом

При одной точке входа ключевым становится параметр вывода:

esbuild src/index.js --bundle --outfile=dist/app.js

Или через API:

outfile: "dist/app.js"

Особенности:

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

Sourcemaps при одной точке входа

Отладка упрощается, так как весь код агрегируется в одном месте:

await esbuild.build({
  entryPoints: ["src/index.js"],
  bundle: true,
  outfile: "dist/app.js",
  sourcemap: true,
});

В этом режиме sourcemap отображает связь между итоговым бандлом и исходным деревом модулей, включая:

  • оригинальные файлы;
  • строки и колонки;
  • структуру импортов.

Минификация и единый граф

Одна точка входа позволяет более агрессивную оптимизацию:

await esbuild.build({
  entryPoints: ["src/index.js"],
  bundle: true,
  outfile: "dist/app.js",
  minify: true,
});

Причина эффективности заключается в том, что весь код доступен как единое пространство оптимизации:

  • инлайнинг функций;
  • удаление мёртвого кода;
  • сокращение имён переменных;
  • устранение промежуточных модулей.

Ограничения модели одной точки входа

Несмотря на универсальность, существуют ограничения:

1. Отсутствие независимого разделения кода

Все зависимости попадают в один граф и часто в один файл. Это упрощает доставку, но снижает гибкость распределения чанков.

2. Линейная структура загрузки

Модель предполагает, что приложение стартует из одного места. При сложных системах с несколькими независимыми приложениями это становится менее удобно.

3. Ограничения на параллельную оптимизацию

Хотя esbuild внутренне параллелизует работу, итоговая структура всё равно централизована.

Поведение при внешних зависимостях

При одной точке входа esbuild обрабатывает внешние зависимости следующим образом:

await esbuild.build({
  entryPoints: ["src/index.js"],
  bundle: true,
  outfile: "dist/app.js",
  external: ["react", "react-dom"],
});

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

  • react и react-dom не включаются в бандл;
  • предполагается их загрузка извне (CDN, отдельные скрипты);
  • граф зависимостей обрывается на границе external.

Интерпретация одной точки входа в контексте модульной системы

Одна точка входа не означает монолитную структуру кода. Напротив, она представляет собой:

  • точку старта;
  • ориентир для построения графа;
  • единицу компиляции.

Модули остаются независимыми, но объединяются на этапе сборки.

Поведение с различными форматами модулей

esbuild поддерживает смешанные типы модулей:

  • ES Modules (import/export);
  • CommonJS (require/module.exports).

При одной точке входа происходит унификация:

// esm
import { a } from "./a.js";

// cjs
const b = require("./b.js");

Оба типа приводятся к единой внутренней модели исполнения.

Роль первой точки в оптимизации кеширования

Одна точка входа часто используется для стабильного кеширования:

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

Это позволяет эффективно использовать хеширование файлов в production-сборках:

await esbuild.build({
  entryPoints: ["src/index.js"],
  bundle: true,
  entryNames: "[dir]/[name]-[hash]",
  outdir: "dist",
});

Итоговая модель исполнения

При одной точке входа esbuild формирует следующую логическую цепочку:

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

Эта модель делает сборку предсказуемой, линейной и оптимизируемой на всех этапах обработки.