Настройка outputFormat: esmodule, commonjs, global

В Parcel при сборке библиотек ключевую роль играет параметр outputFormat, определяющий формат модульной системы результирующего бандла. Он задаёт способ экспорта кода и его совместимость с различными средами выполнения: браузером, Node.js и окружениями без модульной системы.

Поддерживаются три основных режима:

  • esmodule
  • commonjs
  • global

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


Концепция библиотечной сборки в Parcel

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

  • формат экспорта
  • совместимость модулей
  • структура публичного API
  • назначение таргета (browser / node / library context)

Конфигурация выполняется через поле targets в package.json, где описывается поведение сборки для конкретного назначения.

{
  "name": "my-lib",
  "source": "src/index.js",
  "targets": {
    "default": {
      "context": "library",
      "distDir": "dist",
      "outputFormat": "esmodule"
    }
  }
}

outputFormat: esmodule

Формат esmodule генерирует код, совместимый с ECMAScript Modules. Результат использует конструкции import и export, сохраняя статическую структуру зависимостей.

Особенности ESM-вывода

  • сохранение статического анализа модулей
  • поддержка tree-shaking на уровне потребителя
  • совместимость с современными сборщиками (Vite, Rollup, Webpack ESM)
  • возможность частичной загрузки модулей

Пример итогового экспорта

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

Parcel сохраняет структуру модулей настолько, насколько это возможно, избегая лишней агрегации кода в один IIFE-блок.

Контекст применения

Формат используется при:

  • разработке библиотек для современных фронтенд-экосистем
  • публикации пакетов в npm с ESM entry point
  • поддержке tree-shaking в downstream-сборщиках

outputFormat: commonjs

Формат commonjs ориентирован на Node.js и традиционную модульную систему require.

Характеристики CommonJS-вывода

  • использование require() для импорта зависимостей
  • экспорт через module.exports и exports
  • динамическая природа загрузки модулей
  • совместимость с устаревшими Node.js проектами

Пример результата

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

module.exports = { sum };

Особенности поведения

Parcel в этом режиме выполняет трансформацию ESM-кода в CommonJS-структуру, включая:

  • преобразование export default
  • обработку именованных экспортов
  • инлайнинг совместимых модулей при необходимости

Область применения

  • Node.js библиотеки без ESM поддержки
  • старые серверные приложения
  • инструменты, зависящие от require

outputFormat: global

Формат global предназначен для использования библиотеки напрямую в браузере через <script> без модульного загрузчика.

Принцип работы

Код помещается в глобальное пространство имён, обычно через объект window.

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

  global.MyLib = {
    sum
  };
})(this);

Особенности глобального формата

  • отсутствие модульной системы
  • единое глобальное пространство имён
  • немедленная доступность API после загрузки скрипта
  • необходимость ручного контроля конфликтов имён

Типичные сценарии

  • подключение через CDN
  • использование в legacy HTML-проектах
  • встраивание библиотек в сторонние сайты без сборщика

Конфигурация outputFormat через targets

Parcel связывает формат вывода с конкретной целью сборки через targets. Это позволяет одной библиотеке иметь несколько вариантов сборки.

{
  "source": "src/index.js",
  "targets": {
    "esm": {
      "context": "library",
      "outputFormat": "esmodule",
      "distDir": "dist/esm"
    },
    "cjs": {
      "context": "library",
      "outputFormat": "commonjs",
      "distDir": "dist/cjs"
    },
    "umd": {
      "context": "library",
      "outputFormat": "global",
      "distDir": "dist/umd"
    }
  }
}

Такой подход позволяет одновременно поддерживать разные экосистемы без изменения исходного кода.


Влияние outputFormat на структуру зависимостей

Выбор формата определяет, как Parcel обрабатывает граф модулей:

  • ESM сохраняет граф в виде связных импортов
  • CommonJS преобразует зависимости в синхронные вызовы require
  • Global инкапсулирует граф в замыкание и сводит API к одному объекту

При этом оптимизации Parcel (scope hoisting, tree-shaking, dead code elimination) применяются по-разному в зависимости от формата.


Взаимодействие с side effects

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

  • в esmodule Parcel может безопасно удалять неиспользуемый код при корректной аннотации sideEffects
  • в commonjs анализ менее точный из-за динамической природы require
  • в global весь код обычно считается выполняемым сразу, что ограничивает удаление неиспользуемых частей

Совместимость и интероперабельность

Parcel обеспечивает согласованность между форматами через слой интеропа:

  • ESM → CommonJS преобразование учитывает default export
  • CommonJS → ESM создаёт виртуальный default экспорт при необходимости
  • Global формат изолируется от модульной системы, теряя информацию о внутренних экспортах

Поведение при многомодульной сборке

При наличии нескольких entry points Parcel формирует независимые бандлы для каждого target, сохраняя заданный outputFormat. Это влияет на:

  • структуру выходной директории
  • дублирование runtime-частей
  • разделение shared-кода

Оптимизация общего кода зависит от стратегии сборки и конфигурации targets.


Использование outputFormat в библиотечных API

Выбор формата определяет публичный контракт библиотеки:

  • ESM задаёт явную структуру экспорта на уровне языка
  • CommonJS фиксирует API через объект module.exports
  • Global формирует неформализованный интерфейс через глобальный объект

Эти различия влияют на:

  • автодополнение в IDE
  • возможности tree-shaking у потребителя
  • динамическую загрузку модулей
  • интеграцию с bundler-экосистемой

Сравнительная модель поведения форматов

  • ESM: статическая структура, оптимизация на этапе сборки потребителя
  • CommonJS: динамическая загрузка, максимальная совместимость
  • Global: отсутствие модулей, прямое выполнение в окружении браузера

Каждый формат отражает отдельную модель распространения JavaScript-библиотек и требует соответствующей архитектуры при проектировании пакета.