JSX в экосистеме JavaScript рассматривается не как самостоятельный язык, а как синтаксическое расширение, которое транслируется в вызовы функций создания элементов. В контексте SWC преобразование JSX выполняется на этапе компиляции и напрямую влияет на поведение кода в development и production-сборках.
Базовая задача трансформации заключается в превращении декларативного JSX в эквивалентные выражения JavaScript с учётом выбранного JSX runtime, режима сборки и целевой среды выполнения.
Основные входные формы JSX:
React.createElement(…)
jsx,
jsxs, jsxDEV
Выходная форма зависит от конфигурации трансформера и окружения, в котором выполняется сборка.
JSX-пайплайн в SWC разделяется на несколько стадий:
Ключевым отличием SWC является выполнение трансформации без промежуточного байткода и с минимальными аллокациями, что делает поведение трансформации детерминированным и быстрым.
Automatic runtime изменяет структуру выходного кода JSX. Вместо глобального объекта React используются импортируемые функции.
Пример входного JSX:
const el = <Button disabled={true}>Text</Button>;
В production-режиме SWC генерирует компактный вызов:
import { jsx as _jsx } from "react/jsx-runtime";
const el = _jsx(Button, {
disabled: true,
children: "Text"
});
Особенности production-режима:
Дополнительно SWC может инлайнить JSX calls, если включена минификация.
Development-режим ориентирован на диагностику, отладку и интеграцию с fast refresh.
Тот же JSX в development может быть преобразован в:
import { jsxDEV as _jsxDEV } from "react/jsx-dev-runtime";
const el = _jsxDEV(Button, {
disabled: true,
children: "Text"
}, undefined, false, {
fileName: "Component.jsx",
lineNumber: 3,
columnNumber: 11
}, this);
fileName — источник модуля
lineNumber, columnNumber — позиция JSX-узла
this-контекст для legacy-совместимости
Эти данные используются для:
Production:
Development:
JSX children обрабатываются по-разному в зависимости от режима:
Production-пайплайн включает:
Development-пайплайн:
Основные параметры конфигурации задаются через
jsc.transform.react.
{
"jsc": {
"transform": {
"react": {
"runtime": "automatic"
}
}
}
}
Возможные значения:
classic
automatic
{
"jsc": {
"transform": {
"react": {
"development": true
}
}
}
}
Включает:
Используется для кастомных JSX runtimes:
{
"jsc": {
"transform": {
"react": {
"runtime": "automatic",
"importSource": "@emotion/react"
}
}
}
}
В этом случае SWC генерирует:
import { jsx } from "@emotion/react/jsx-runtime";
JSX-трансформация тесно связана с минификатором SWC.
В production pipeline:
Минификация дополнительно влияет на JSX output:
{isActive && <Modal />}
Трансформируется в:
isActive && _jsx(Modal, {});
Дополнительно:
isActive && _jsxDEV(Modal, {}, undefined, false, { ...meta }, this);
Сохраняются:
Fragments имеют отдельную стратегию генерации.
Production:
<>Hello</>
import { Fragment as _Fragment } from "react/jsx-runtime";
_jsx(_Fragment, {
children: "Hello"
});
Development:
_jsxDEV(_Fragment, {
children: "Hello"
}, undefined, false, meta, this);
Fast Refresh зависит от стабильности JSX output.
Development mode обеспечивает:
Production mode полностью исключает:
Хотя JSX напрямую не отвечает за tree shaking, его трансформация влияет на возможности удаления кода:
Особенно важно при использовании automatic runtime, где импорт функций становится статически анализируемым.
JSX spread:
<Button {...props} disabled />
Production:
Development:
Вложенные конструкции:
<div>
<Header title={<Title />} />
</div>
Production трансформация:
Development:
JSX pipeline в SWC характеризуется:
Разница между development и production режимами проявляется не только в результате генерации кода, но и в стоимости самой трансформации: development pipeline включает дополнительные шаги генерации метаданных, что увеличивает объём работы компилятора, тогда как production стремится к минимальному числу операций преобразования.
SWC поддерживает несколько поколений JSX runtime:
Это обеспечивает совместимость: