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 основан на новом механизме 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 позволяет сборщикам эффективнее
удалять неиспользуемые части.
Различие между режимами проявляется не только на уровне синтаксиса, но и в архитектуре генерируемого кода.
Структура вызовов
React.createElement
jsx,
jsxs, jsxDEV
Зависимости
Гибкость оптимизации
Совместимость
Внутри компилятора JSX преобразуется на этапе AST-трансформации. SWC анализирует исходный код и в зависимости от конфигурации выбирает стратегию генерации.
Для классического режима используется псевдостратегия:
React.createElement
Для автоматического режима:
automatic)
jsx-runtime или
jsx-dev-runtime
jsx / jsxs
Выбор 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 сценарии трансформации аналогичны, однако важную роль
играет параметр jsx в tsconfig.json:
react — классический runtime
react-jsx — автоматический runtime
react-jsxdev — development-вариант автоматического runtime
SWC при использовании совместно с TypeScript фактически дублирует поведение tsc, но выполняет трансформацию быстрее за счёт более низкоуровневой реализации.
Автоматический runtime вводит различие между режимами сборки.
Development runtime (jsxDEV) содержит дополнительные
параметры:
Это позволяет улучшать диагностику ошибок и предупреждения во время разработки.
Production runtime (jsx, jsxs) исключает
метаданные, оставляя только минимально необходимую структуру вызова.
Классический runtime не делает такого разделения, используя один универсальный механизм.
Автоматический runtime позволяет SWC выполнять более агрессивные оптимизации:
React.createElement
Классический runtime ограничивает такие оптимизации из-за глобального характера React-объекта и менее гранулярной структуры вызовов.
Классический runtime остаётся важным для:
React.createElement
Автоматический runtime используется в:
SWC выполняет выбор runtime на этапе компиляции, и этот выбор фиксирует структуру всего дальнейшего JavaScript-кода. Разница между режимами не ограничивается синтаксисом: она затрагивает модель зависимостей, стратегию импорта, оптимизацию и взаимодействие с рантаймом React.