Поле env: интеграция с browserslist

Конфигурационное поле env в SWC отвечает за применение трансформаций ECMAScript в зависимости от целевых окружений выполнения. В основе механизма лежит интеграция с экосистемой совместимости браузеров, где ключевую роль играет формат запросов browserslist и правила определения поддерживаемых функций JavaScript в разных средах.

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

Внутри env задаётся параметр targets, который принимает выражение в формате browserslist. Это может быть строка, массив строк или ссылка на внешнюю конфигурацию browserslist. После анализа этого выражения SWC формирует внутренний список поддерживаемых возможностей ECMAScript для каждой целевой платформы.

Источники конфигурации browserslist

SWC опирается на стандартную систему browserslist, которая определяет список поддерживаемых браузеров через несколько уровней конфигурации:

  • поле browserslist в package.json
  • файл .browserslistrc
  • отдельные конфигурационные файлы .browserslistrc, .browserslist
  • переменные окружения BROWSERSLIST

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

Структура поля env в SWC

Типичная конфигурация выглядит как часть объекта jsc:

{
  "jsc": {
    "target": "es2017",
    "parser": {
      "syntax": "ecmascript"
    },
    "transform": {},
    "env": {
      "targets": "> 0.25%, not dead"
    }
  }
}

Поле env.targets задаёт условия, при которых SWC определяет необходимость транспиляции современных возможностей языка. Значение может включать сложные выражения, аналогичные тем, что используются в Babel preset-env.

Дополнительно допускается передача массива:

{
  "env": {
    "targets": ["chrome 90", "firefox 88", "safari 14"]
  }
}

В таком случае SWC объединяет поддержку всех перечисленных окружений и выбирает минимальный общий набор возможностей языка.

Взаимодействие env и jsc.target

Параметры jsc.target и env.targets выполняют разные функции и не являются взаимозаменяемыми.

jsc.target определяет базовый уровень генерации JavaScript-кода (например, ES5, ES2015, ES2020). Он влияет на синтаксическую форму выходного кода.

env.targets определяет, какие языковые фичи требуют трансформации в зависимости от реальных браузеров или runtime-сред.

При совместном использовании SWC сначала ориентируется на target, а затем применяет дополнительную фильтрацию через env.targets. Это позволяет, например, генерировать код уровня ES2019, но при этом полифиллить или трансформировать отдельные возможности, отсутствующие в старых браузерах.

Алгоритм выбора трансформаций

Процесс принятия решения в SWC можно представить в виде последовательности:

  1. Разбор конфигурации env.targets
  2. Получение данных browserslist (локальных или встроенных)
  3. Сопоставление целевых браузеров с таблицей поддержки ECMAScript
  4. Определение набора неподдерживаемых возможностей
  5. Генерация соответствующих трансформаций AST

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

Поддержка спецификации browserslist

SWC интерпретирует выражения browserslist аналогично инструментам экосистемы фронтенда. Поддерживаются операторы:

  • процентные значения покрытия рынка (> 0.5%)
  • исключения (not dead)
  • конкретные версии браузеров (chrome 100)
  • диапазоны версий (firefox 78-90)

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

Использование внешнего файла browserslist

Если проект уже содержит централизованную конфигурацию browserslist, поле env.targets может быть опущено. В этом случае SWC автоматически считывает настройки из окружения проекта.

Пример package.json:

{
  "browserslist": [
    "> 1%",
    "last 2 versions",
    "not dead"
  ]
}

SWC при отсутствии явного env.targets использует эти значения как источник истины. Это важно для унификации поведения сборки между SWC, PostCSS и другими инструментами.

Поведение при конфликте конфигураций

Если одновременно заданы:

  • env.targets в SWC
  • поле browserslist в package.json
  • .browserslistrc

то приоритет определяется следующим образом:

  1. env.targets в SWC (наивысший приоритет)
  2. переменные окружения BROWSERSLIST
  3. конфигурационные файлы browserslist
  4. стандартные дефолты (modern browsers)

Такое поведение позволяет локально переопределять стратегию транспиляции без изменения глобальной конфигурации проекта.

Пример конфигурации с явным env

{
  "jsc": {
    "parser": {
      "syntax": "typescript"
    },
    "target": "es2020",
    "transform": {
      "react": {
        "runtime": "automatic"
      }
    },
    "env": {
      "targets": [
        "chrome >= 80",
        "edge >= 80",
        "firefox >= 75",
        "safari >= 13"
      ]
    }
  }
}

В таком варианте SWC будет генерировать код уровня ES2020, но дополнительно учитывать ограничения Safari 13 и Firefox 75, исключая использование неподдерживаемых возможностей.

Роль env в трансформации новых возможностей ECMAScript

Поле env влияет на выбор трансформаций для таких конструкций, как:

  • optional chaining
  • nullish coalescing
  • class fields
  • private methods
  • async/await (в зависимости от целевого окружения)
  • for-await-of

Если целевые браузеры поддерживают синтаксис нативно, SWC может полностью исключить соответствующие трансформации, уменьшая размер выходного кода.

Связь с модулем определения возможностей

SWC использует внутреннюю модель совместимости, в которой каждая языковая фича описана как набор требований к runtime. При обработке env.targets происходит сопоставление:

  • feature → минимальная версия браузера
  • браузер → поддерживаемые версии ECMAScript

Результатом становится список фич, требующих преобразования.

Интеграция с monorepo и workspace структурами

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

Особенность заключается в том, что env.targets, заданный в локальном .swcrc, не распространяется автоматически на соседние пакеты. Это может приводить к различиям в генерации кода между пакетами одного репозитория при отсутствии централизованной политики конфигурации.

Кэширование результатов browserslist

Для ускорения компиляции SWC кэширует:

  • результат парсинга browserslist выражений
  • список разрешённых версий браузеров
  • вычисленный набор ECMAScript возможностей

При изменении конфигурации browserslist кэш инвалидируется. В CI-средах это особенно важно, поскольку повторное использование старого кэша может привести к несоответствию целевым окружениям.

Отличия от Babel preset-env

Хотя концептуально env в SWC соответствует @babel/preset-env, существуют архитектурные различия:

  • SWC выполняет трансформации через Rust-реализацию AST, что влияет на стратегию оптимизаций
  • отсутствует гибкая система плагинов на уровне preset-env
  • выбор трансформаций более жёстко связан с внутренней таблицей поддержки ECMAScript

При этом логика browserslist остаётся совместимой, что позволяет переносить конфигурации между инструментами без изменений.

Особенности работы с устаревшими browserslist данными

При использовании устаревших версий browserslist возможны расхождения в интерпретации выражений. SWC нормализует входные данные, но не гарантирует идентичность с последними версиями спецификации browserslist.

В проектах с длительным жизненным циклом сборки это может проявляться в различиях между локальной и CI-средой, если версии зависимостей не синхронизированы.

Практическое влияние на размер бандла

Правильно настроенное поле env.targets напрямую влияет на итоговый размер выходного кода. Более современные целевые окружения приводят к:

  • уменьшению количества транспиляций
  • сокращению вспомогательного кода
  • снижению объёма polyfill-зависимостей на уровне сборщика

Более старые целевые окружения, наоборот, увеличивают количество преобразований AST и приводят к генерации более универсального, но менее компактного кода.