Глобальное имя в форматах UMD и IIFE в контексте сборки Rollup
определяет точку доступа к библиотеке после подключения через
<script> без модульной системы. От корректного выбора
имени зависит предсказуемость использования, отсутствие конфликтов в
глобальном пространстве и совместимость с экосистемами, где отсутствует
ESM.
Формат IIFE (Immediately Invoked Function Expression) в Rollup генерирует самовызывающуюся функцию, которая изолирует внутренний код модуля, но при этом может экспортировать результат в глобальную область видимости.
Типичный результат сборки:
var MyLib = (function () {
'use strict';
function add(a, b) {
return a + b;
}
return {
add
};
}());
Ключевой момент заключается в том, что переменная MyLib
становится глобальной только если бандл подключён напрямую в браузере
без модульного загрузчика. Именно это имя определяет, как библиотека
будет доступна пользователю.
В современных средах глобальный объект может быть разным:
window в браузереglobal в Node.js (при не-модульной сборке)globalThis как универсальная абстракцияRollup при генерации IIFE опирается на конфигурацию
output.name, которая и задаёт глобальный идентификатор.
UMD (Universal Module Definition) расширяет IIFE, добавляя поддержку AMD и CommonJS. Это делает имя глобальной переменной частью более сложной системы ветвления:
(function (global, factory) {
if (typeof define === 'function' && define.amd) {
define([], factory);
} else if (typeof exports !== 'undefined') {
module.exports = factory();
} else {
global.MyLib = factory();
}
}(this, (function () {
'use strict';
function add(a, b) {
return a + b;
}
return {
add
};
})));
Здесь MyLib становится ключевой точкой привязки в
глобальном пространстве. Ошибка в выборе имени приводит к конфликтам или
недоступности библиотеки в legacy-окружениях.
В Rollup имя глобальной переменной задаётся через
output.name:
export default {
input: 'src/index.js',
output: {
file: 'dist/bundle.umd.js',
format: 'umd',
name: 'MyLib'
}
};
Это значение используется:
Имя становится частью публичного API при использовании через
<script>:
<script src="bundle.umd.js"></script>
<script>
MyLib.add(2, 3);
</script>
Если имя выбрано неудачно, возникают следующие проблемы:
Чаще всего глобальное имя выводится из имени npm-пакета. Например:
lodash → _moment → momentchart.js → ChartRollup не выполняет автоматическую нормализацию в большинстве
случаев, поэтому явное задание output.name обязательно для
предсказуемости.
Для глобальных объектов предпочтителен PascalCase:
MyLibraryHttpClientDateUtilsCamelCase также допустим, но чаще используется для внутренних API:
myLibrary (менее предпочтительно для глобала)Причина выбора PascalCase связана с традицией конструкторов и классов в JavaScript, что снижает риск конфликтов с примитивными значениями.
Использование слишком общих идентификаторов создаёт риск коллизий:
UtilsHelperAppLibТакие имена часто уже присутствуют в глобальной области других библиотек или приложений.
Для сложных библиотек используется объектное пространство имён:
output: {
name: 'MyCompany.MyLib',
format: 'umd'
}
Результат:
global.MyCompany.MyLib = factory();
Это снижает вероятность конфликтов, но увеличивает длину обращения.
Использование такого подхода оправдано для корпоративных SDK и крупных систем.
Rollup поддерживает точечную нотацию, которая превращается в цепочку объектов:
name: 'Platform.Services.Http'
Генерация:
global.Platform = global.Platform || {};
global.Platform.Services = global.Platform.Services || {};
global.Platform.Services.Http = factory();
Такой подход обеспечивает безопасное расширение глобального пространства без перезаписи существующих значений.
Минификация кода внутри IIFE не влияет на имя глобальной переменной,
если оно задано через output.name. Однако внутренние
свойства объекта могут быть сокращены:
return {
add,
subtract,
multiply
};
После минификации:
return { a, b, c };
Глобальное имя при этом остаётся неизменным, поскольку оно является частью контракта внешнего API.
Основные сценарии конфликтов:
window.Utils = ...
Если другая библиотека уже использует Utils, происходит
скрытая замена функциональности.
Код может случайно полагаться на существующее глобальное имя:
if (window.Utils) {
window.Utils.format();
}
При подключении другой версии библиотеки поведение становится нестабильным.
UMD/IIFE-бандлы зависят от порядка подключения:
<script src="core.js"></script>
<script src="plugin.js"></script>
Если plugin.js ожидает глобальное имя Core,
оно должно быть гарантированно создано ранее.
| Характеристика | IIFE | UMD |
|---|---|---|
| Глобальная переменная | Да | Да |
| AMD поддержка | Нет | Да |
| CommonJS | Нет | Да |
| Использование name | output.name | output.name |
| Сложность кода | Ниже | Выше |
UMD требует более строгого подхода к именованию, поскольку имя используется в нескольких контекстах сразу.
Современные бандлы часто опираются на globalThis:
globalThis.MyLib = factory();
Это устраняет необходимость различать window,
global и self. Однако имя переменной остаётся
тем же самым ключевым элементом API.
name: 'AcmeHttpClient'
Снижает риск конфликта в публичных окружениях.
name: 'Acme.Network.HttpClient'
Используется в больших экосистемах.
Иногда допускаются короткие имена, если библиотека становится стандартом де-факто:
VueReactRxВ таких случаях имя становится частью индустриального соглашения.
Глобальное имя влияет на:
Неудачное имя приводит к необходимости дополнительных обёрток:
const Http = window.SomeVeryLongAndInconsistentName.Http;
При использовании TypeScript глобальное имя часто дублируется в декларациях:
declare global {
const MyLib: {
add(a: number, b: number): number;
};
}
Несоответствие между output.name и декларацией приводит
к ошибкам времени выполнения при использовании UMD-бандла.
Процесс выбора глобального идентификатора обычно включает:
Имя, заданное в Rollup, становится контрактом между сборкой и средой выполнения, поэтому любые изменения требуют версионирования и миграционной стратегии.