Поддержка conditions: browser, import, require, default

Поле conditions управляет тем, какие экспортируемые варианты модулей выбираются при сборке зависимостей. Оно напрямую связано с полем exports в package.json, где пакеты описывают различные точки входа в зависимости от окружения выполнения.

В основе механизма лежит стандарт Conditional Exports из Node.js и экосистемы ESM, где один и тот же пакет может предоставлять разные файлы для разных сценариев: браузер, Node.js, require, import и другие пользовательские условия.


Базовая модель conditional exports

В package.json зависимость может описывать несколько вариантов одного и того же модуля:

{
  "exports": {
    ".": {
      "browser": "./dist/browser.js",
      "import": "./dist/esm.js",
      "require": "./dist/cjs.js",
      "default": "./dist/default.js"
    }
  }
}

Каждый ключ внутри exports — это условие. Оно выбирается в зависимости от окружения и инструментов сборки.

esbuild использует поле conditions для управления тем, какие из этих ключей считать активными.


Роль conditions в резолве модулей

В конфигурации сборщика conditions представляет собой массив строк:

{
  conditions: ["browser", "import", "require"]
}

Каждая строка — это имя условия, которое участвует в выборе соответствующего поля в exports.

При разрешении импорта esbuild:

  1. Читает exports из package.json
  2. Проверяет совпадение условий в порядке приоритета
  3. Выбирает первый подходящий вариант

Если совпадений нет, используется default.


Условие import

Смысл

Условие import применяется при использовании ES Modules:

  • import x from 'package'
  • динамический import()

Поведение

Если включено:

conditions: ["import"]

то при наличии:

"exports": {
  ".": {
    "import": "./esm.js",
    "require": "./cjs.js"
  }
}

будет выбран esm.js.

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

  • современные браузерные бандлы
  • ESM-сборка Node.js
  • tree-shaking ориентированные пайплайны

Условие require

Смысл

Условие require применяется при CommonJS-совместимости:

  • require('package')

Поведение

При конфигурации:

conditions: ["require"]

и exports:

{
  ".": {
    "import": "./esm.js",
    "require": "./cjs.js"
  }
}

будет выбран CommonJS-файл.

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

  • Node.js проекты без ESM
  • старые сборки
  • совместимость с legacy-кодом

Условие browser

Смысл

Условие browser предназначено для замены модулей при сборке под браузер.

Поведение

conditions: ["browser", "import", "require"]

и:

{
  ".": {
    "browser": "./browser.js",
    "import": "./esm.js",
    "require": "./cjs.js"
  }
}

Приоритет:

  1. browser
  2. import
  3. require
  4. default

Особенности

Условие browser может:

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

Условие default

Смысл

default — резервный вариант, используемый, если ни одно условие не совпало.

Поведение

{
  ".": {
    "browser": "./browser.js",
    "import": "./esm.js",
    "default": "./fallback.js"
  }
}

Если conditions не содержит совпадающих ключей, выбирается fallback.js.


Приоритет условий

esbuild обрабатывает условия последовательно, в порядке массива conditions.

Пример:

conditions: ["browser", "require", "import"]

При таком порядке:

  1. сначала проверяется browser
  2. затем require
  3. затем import
  4. затем default

Приоритет не фиксирован внутри esbuild — он определяется конфигурацией сборки.


Взаимодействие с платформой (platform)

Поле conditions тесно связано с platform:

{
  platform: "browser",
  conditions: ["browser", "import", "require"]
}

или:

{
  platform: "node",
  conditions: ["require", "import"]
}

Связь поведения

  • platform: browser усиливает роль browser
  • platform: node чаще приводит к выбору require или import

Поведение без conditions

Если conditions не указаны, используется стандартный набор:

  • import
  • require
  • default

Но без явного browser поведение может не учитывать браузерные замены.


Пример реального разрешения

package.json зависимости

{
  "name": "lib",
  "exports": {
    ".": {
      "browser": "./browser.js",
      "import": "./esm.js",
      "require": "./cjs.js",
      "default": "./fallback.js"
    }
  }
}

esbuild конфигурация

{
  platform: "browser",
  conditions: ["browser", "import", "default"]
}

Результат

  • в браузерной сборке → browser.js
  • при отсутствии browser → esm.js
  • если нет esm → fallback.js

Расширенные пользовательские условия

Помимо стандартных значений:

  • browser
  • import
  • require
  • default

могут использоваться кастомные условия:

{
  ".": {
    "production": "./prod.js",
    "development": "./dev.js"
  }
}

И конфигурация:

conditions: ["production"]

Особенность

esbuild не интерпретирует смысл условий — он только сопоставляет строки.


Совместимость с Node.js resolution

Node.js поддерживает аналогичную систему условий через:

  • exports
  • imports
  • --conditions

Разница:

  • Node.js использует runtime resolution
  • esbuild применяет условия на этапе сборки

Это приводит к тому, что conditions в esbuild фактически фиксируют выбор модулей заранее.


Типовые ошибки при использовании conditions

Перепутанный порядок

conditions: ["require", "browser"]

В результате браузерный код может быть проигнорирован.


Отсутствие browser в браузерной сборке

Без browser:

  • Node.js версии модулей могут попасть в клиентский бандл

Конфликт import/require

Если пакет не строго разделяет ESM и CJS, выбор может стать непредсказуемым при неправильной конфигурации условий.


Влияние на tree-shaking и размер бандла

Выбор через conditions влияет на:

  • наличие side-effect free модулей
  • возможность удаления неиспользуемого кода
  • итоговый размер бандла

Особенно критично при наличии:

  • отдельных CJS/ESM сборок
  • browser polyfills
  • feature-based exports

Практическая модель выбора условий

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

conditions: ["browser", "import", "require", "default"]

или для Node.js:

conditions: ["import", "require", "default"]

или строгая ESM:

conditions: ["import", "default"]

Резюме поведения резолвинга

Алгоритм выбора:

  1. Получение exports
  2. Проверка conditions по порядку
  3. Поиск совпадения ключа условия
  4. Возврат первого подходящего файла
  5. При отсутствии — default

Этот механизм делает esbuild предсказуемым инструментом для построения разных таргетных сборок из одного набора зависимостей.