Классический и автоматический runtime

SWC реализует трансформацию JSX через два принципиально разных режима работы runtime: классический и автоматический. Эти режимы определяют способ преобразования JSX-выражений в JavaScript-код и напрямую влияют на размер бандла, требования к импортам и совместимость с различными версиями React-экосистемы.

Классический runtime опирается на явное использование функции создания элементов, традиционно ассоциированной с React.createElement. В этом режиме каждый JSX-узел преобразуется в вызов функции, которая принимает тип элемента, свойства и дочерние узлы.

Основная особенность заключается в необходимости наличия импортируемого объекта React в области видимости файла:

import React from "react";

const element = <div className="box">Text</div>;

После трансформации SWC код принимает форму:

import React from "react";

const element = React.createElement(
  "div",
  { className: "box" },
  "Text"
);

Классический runtime характеризуется следующими свойствами:

Явная зависимость от React Каждый файл, содержащий JSX, должен иметь доступ к объекту React, даже если он не используется напрямую.

Стабильность и предсказуемость Модель трансформации остается неизменной на протяжении длительного времени, что обеспечивает совместимость с legacy-кодом и старыми версиями React.

Увеличенный размер бандла Из-за необходимости импортировать React и использования более многословных вызовов результирующий код может быть менее компактным.

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


Автоматический runtime

Автоматический runtime основан на новом механизме JSX-трансформации, введённом в современных версиях React и поддерживаемом SWC. Он устраняет необходимость явного импорта React в каждом файле.

JSX:

const element = <div className="box">Text</div>;

Трансформируется в зависимости от настроек компилятора в один из вариантов импорта функций JSX:

import { jsx as _jsx } from "react/jsx-runtime";

const element = _jsx("div", {
  className: "box",
  children: "Text"
});

или для development-режима:

import { jsxDEV as _jsxDEV } from "react/jsx-dev-runtime";

const element = _jsxDEV("div", {
  className: "box",
  children: "Text"
}, undefined, false, undefined, this);

Ключевые характеристики автоматического runtime:

Отсутствие явного React-import React больше не требуется импортировать исключительно ради JSX, что уменьшает шаблонный код.

Разделение production и development runtime Используются разные функции: jsx для production и jsxDEV для режима разработки, что позволяет внедрять дополнительные проверки и метаданные.

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

Оптимизация tree-shaking Модульная структура импортов из react/jsx-runtime позволяет сборщикам эффективнее удалять неиспользуемые части.


Сравнение моделей трансформации

Различие между режимами проявляется не только на уровне синтаксиса, но и в архитектуре генерируемого кода.

Структура вызовов

  • Классический runtime: единый объект React.createElement
  • Автоматический runtime: специализированные функции jsx, jsxs, jsxDEV

Зависимости

  • Классический runtime требует полного React-объекта
  • Автоматический runtime использует точечные импорты

Гибкость оптимизации

  • Классический runtime ограничен общими вызовами
  • Автоматический runtime позволяет более тонкие оптимизации компилятора

Совместимость

  • Классический runtime сохраняет максимальную обратную совместимость
  • Автоматический runtime требует современного React и соответствующего JSX runtime API

Поведение трансформации JSX в SWC

Внутри компилятора JSX преобразуется на этапе AST-трансформации. SWC анализирует исходный код и в зависимости от конфигурации выбирает стратегию генерации.

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

  1. Обнаружение JSX-элемента
  2. Замена на React.createElement
  3. Добавление импорта React при необходимости

Для автоматического режима:

  1. Обнаружение JSX-элемента
  2. Определение используемого runtime (automatic)
  3. Генерация импорта из jsx-runtime или jsx-dev-runtime
  4. Замена JSX на вызовы функций jsx / jsxs

Конфигурация SWC

Выбор runtime определяется настройками трансформации JSX.

Пример конфигурации для классического режима:

{
  "jsc": {
    "transform": {
      "react": {
        "runtime": "classic"
      }
    }
  }
}

Пример конфигурации для автоматического режима:

{
  "jsc": {
    "transform": {
      "react": {
        "runtime": "automatic"
      }
    }
  }
}

Дополнительные параметры:

importSource Позволяет изменить источник функций JSX:

{
  "jsc": {
    "transform": {
      "react": {
        "runtime": "automatic",
        "importSource": "preact"
      }
    }
  }
}

В этом случае вместо react/jsx-runtime будет использоваться альтернативный runtime, например Preact.


Влияние на архитектуру проекта

Выбор runtime определяет стиль организации кода.

Классический runtime приводит к более явной зависимости от React как глобальной концепции модуля. Каждый файл становится частью единой модели React-экземпляра.

Автоматический runtime смещает модель в сторону модульности: JSX рассматривается как независимый синтаксический сахар, не требующий глобального объекта.


Особенности поведения в TypeScript-проектах

В TypeScript сценарии трансформации аналогичны, однако важную роль играет параметр jsx в tsconfig.json:

  • react — классический runtime
  • react-jsx — автоматический runtime
  • react-jsxdev — development-вариант автоматического runtime

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


Поведение в development и production

Автоматический runtime вводит различие между режимами сборки.

Development runtime (jsxDEV) содержит дополнительные параметры:

  • имя компонента
  • позицию в дереве
  • флаг строгой проверки

Это позволяет улучшать диагностику ошибок и предупреждения во время разработки.

Production runtime (jsx, jsxs) исключает метаданные, оставляя только минимально необходимую структуру вызова.

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


Тонкости оптимизации

Автоматический runtime позволяет SWC выполнять более агрессивные оптимизации:

  • инлайн JSX-вызовов
  • устранение лишних импортов
  • более точное tree-shaking
  • сокращение повторяющихся вызовов React.createElement

Классический runtime ограничивает такие оптимизации из-за глобального характера React-объекта и менее гранулярной структуры вызовов.


Совместимость с экосистемой

Классический runtime остаётся важным для:

  • устаревших React-проектов
  • библиотек, завязанных на React.createElement
  • сборок без поддержки JSX runtime API

Автоматический runtime используется в:

  • современных React-приложениях
  • проектах с Vite, Next.js и аналогичными сборщиками
  • библиотеках, ориентированных на минимальный размер бандла

Итоговое поведение трансформации

SWC выполняет выбор runtime на этапе компиляции, и этот выбор фиксирует структуру всего дальнейшего JavaScript-кода. Разница между режимами не ограничивается синтаксисом: она затрагивает модель зависимостей, стратегию импорта, оптимизацию и взаимодействие с рантаймом React.