Опция globalName для IIFE

В режиме сборки JavaScript-кода в формат IIFE (Immediately Invoked Function Expression) весь модульный код объединяется в одну самовызывающуюся функцию. Такой формат используется для запуска скриптов напрямую в браузере без систем модулей, при этом экспортируемые значения становятся свойствами одного глобального объекта.

При использовании esbuild с форматом iife возникает ключевая проблема: как именно назвать глобальную переменную, в которую будут помещены экспортируемые значения. Для этого применяется опция globalName.


Роль globalName в IIFE-сборке

При сборке в формате IIFE esbuild оборачивает весь код в конструкцию вида:

(function () {
  // скомпилированный код модуля
})();

Однако экспортированные значения должны быть доступны снаружи. Без дополнительной настройки esbuild не знает, как назвать объект, который будет содержать эти экспорты.

Опция globalName задаёт имя этого объекта в глобальной области видимости.


Базовый пример использования

import * as esbuild from 'esbuild';

esbuild.build({
  entryPoints: ['src/index.js'],
  bundle: true,
  format: 'iife',
  globalName: 'MyLibrary',
  outfile: 'dist/bundle.js'
});

После сборки результат будет выглядеть концептуально следующим образом:

var MyLibrary = (function () {
  function hello() {
    return "Hello";
  }

  return {
    hello: hello
  };
})();

Теперь все экспортированные сущности доступны через MyLibrary.


Поведение при наличии export

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

export function sum(a, b) {
  return a + b;
}

export const version = "1.0.0";

После сборки с globalName: "Calc":

var Calc = (() => {
  function sum(a, b) {
    return a + b;
  }

  const version = "1.0.0";

  return {
    sum,
    version
  };
})();

Таким образом, globalName становится контейнером для всех экспортов.


Влияние на область видимости

Использование globalName не только определяет имя экспортируемого объекта, но и влияет на способ интеграции библиотеки в глобальную среду:

  • переменная создаётся в глобальном scope (window в браузере)
  • возможна перезапись существующих переменных при совпадении имени
  • отсутствует изоляция модулей на уровне импортов

Поэтому выбор имени требует строгого контроля уникальности.


Использование с namespace-экспортами

При экспорте пространства имён:

export const math = {
  add(a, b) {
    return a + b;
  }
};

Результирующая структура:

var Utils = (() => {
  const math = {
    add(a, b) {
      return a + b;
    }
  };

  return { math };
})();

Доступ:

Utils.math.add(2, 3);

Особенности генерации кода

esbuild оптимизирует структуру IIFE, но при этом соблюдает следующие принципы:

  • экспортируемые сущности собираются в единый объект
  • локальные переменные остаются внутри замыкания
  • имя globalName используется только как точка входа наружу
  • при отсутствии экспортов объект всё равно создаётся пустым

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

Если формат установлен в iife, но globalName не указан, esbuild не может корректно сформировать глобальный интерфейс для экспортов. В зависимости от структуры кода это приводит к:

  • отсутствию предсказуемого глобального объекта
  • невозможности обращения к экспортам извне
  • генерации кода, ориентированного только на побочные эффекты

Работа с несколькими entry points

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

esbuild.build({
  entryPoints: ['a.js', 'b.js'],
  bundle: true,
  format: 'iife',
  globalName: 'App',
  outfile: 'dist/app.js'
});

esbuild объединяет все экспорты в один объект:

var App = (() => {
  // код a.js
  // код b.js

  return {
    // объединённые экспорты
  };
})();

Конфликты имён разрешаются на этапе сборки через внутреннюю систему нейминга esbuild.


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

При подключении скомпилированного файла в браузере:

<script src="bundle.js"></script>
<script>
  App.run();
</script>

globalName становится единственной точкой доступа к функциональности библиотеки без использования модулей ES.


Ограничения подхода

Использование globalName в IIFE-формате накладывает архитектурные ограничения:

  • невозможность tree-shaking на уровне потребления
  • отсутствие динамического импорта
  • потенциальные конфликты глобальных имён
  • ограниченная масштабируемость по сравнению с ESM

Несмотря на это, формат остаётся востребованным для встраиваемых библиотек и legacy-среды.


Сочетание с другими опциями esbuild

Опция globalName часто используется совместно с:

  • minify — уменьшение размера итогового кода
  • sourcemap — генерация карт исходного кода
  • target — контроль совместимости с браузерами
  • define — подстановка констант на этапе сборки

Пример комплексной конфигурации:

esbuild.build({
  entryPoints: ['src/index.js'],
  bundle: true,
  format: 'iife',
  globalName: 'Core',
  minify: true,
  sourcemap: true,
  target: ['es2017'],
  outfile: 'dist/core.js'
});

Принцип формирования имени

Имя, указанное в globalName, должно соответствовать следующим требованиям:

  • быть валидным идентификатором JavaScript
  • не совпадать с существующими глобальными объектами
  • отражать назначение библиотеки
  • сохранять единообразие при использовании в разных средах

Нарушение этих правил приводит к конфликтам на уровне глобального scope.


Внутренняя модель экспорта

Механизм работы можно описать следующим образом:

  1. анализ export-выражений
  2. генерация локальных функций и переменных
  3. упаковка всех экспортов в объект
  4. привязка объекта к имени globalName
  5. оборачивание всего кода в IIFE

Эта модель обеспечивает предсказуемую структуру итогового бандла при минимальных накладных расходах.