esbuild поддерживает трансформацию JSX как часть встроенного
компилятора, без необходимости Babel или дополнительных транспилеров.
Основной принцип работы заключается в том, что JSX не исполняется
напрямую — он преобразуется в вызовы функций, определяемые настройками
jsxFactory, jsxFragment и
jsxImportSource.
JSX в контексте Esbuild может работать в двух режимах:
jsxImportSourceРазница между ними определяет совместимость с библиотеками вроде Preact и Solid.
Основные параметры конфигурации:
import { build } from 'esbuild';
build({
entryPoints: ['src/index.jsx'],
bundle: true,
outfile: 'dist/app.js',
jsx: 'transform',
jsxFactory: 'h',
jsxFragment: 'Fragment'
});
jsx: 'transform' — включает преобразование JSXjsxFactory — функция создания элементовjsxFragment — функция для фрагментов
<>...</>Такой режим используется для библиотек, которые требуют явного runtime, например Preact в legacy-режиме.
Preact совместим с JSX через два основных подхода: классический runtime и автоматический runtime.
build({
entryPoints: ['src/index.jsx'],
bundle: true,
outfile: 'dist/app.js',
jsxFactory: 'h',
jsxFragment: 'Fragment'
});
И код приложения:
import { h, Fragment } from 'preact';
const App = () => (
<>
<h1>Приложение</h1>
</>
);
Здесь JSX превращается в:
h(Fragment, null,
h('h1', null, 'Приложение')
);
Современный подход использует preact/jsx-runtime:
build({
entryPoints: ['src/index.jsx'],
bundle: true,
outfile: 'dist/app.js',
jsx: 'automatic',
jsxImportSource: 'preact'
});
Код:
const App = () => (
<h1>Приложение</h1>
);
Автоматически компилируется в импортированные функции JSX runtime без
явного h.
Solid использует собственную модель реактивности и требует автоматического JSX runtime.
build({
entryPoints: ['src/index.jsx'],
bundle: true,
outfile: 'dist/app.js',
jsx: 'automatic',
jsxImportSource: 'solid-js'
});
function Counter() {
return <button>Клик</button>;
}
Solid не использует виртуальный DOM. JSX напрямую компилируется в реактивные вызовы:
import { template as _$template } from "solid-js/web";
и далее создаются оптимизированные DOM-узлы.
jsxImportSource: 'solid-js' обязателенИспользуется в:
Характеристики:
jsxFactoryh-вызовИспользуется в:
Характеристики:
jsx: 'automatic'jsxImportSourceПри использовании TypeScript с JSX в Esbuild важно согласовать настройки:
{
"compilerOptions": {
"jsx": "react-jsx",
"jsxImportSource": "preact"
}
}
или для Solid:
{
"compilerOptions": {
"jsx": "react-jsx",
"jsxImportSource": "solid-js"
}
}
Esbuild при этом игнорирует TypeScript JSX трансформацию и применяет собственную.
Esbuild позволяет подключать любую библиотеку, предоставляющую JSX runtime.
build({
entryPoints: ['src/index.jsx'],
bundle: true,
outfile: 'dist/app.js',
jsx: 'automatic',
jsxImportSource: './my-jsx-runtime'
});
Структура runtime:
export function jsx(type, props) {
return { type, props };
}
export function jsxs(type, props) {
return { type, props };
}
export function Fragment(props) {
return props.children;
}
Esbuild выполняет несколько оптимизаций:
FragmentПример:
<div>
<span>1</span>
<span>2</span>
</div>
может быть преобразован в минимальный набор вызовов без промежуточных структур.
JSX в Esbuild корректно работает с большинством современных UI-решений:
preact/jsx-runtime)solid-js)Ключевым фактором остаётся выбор jsxImportSource,
определяющий, какие функции будут импортироваться при трансформации.
Если используется jsx: 'automatic', но не задан
jsxImportSource, результатом становится некорректный импорт
или падение сборки.
При использовании Preact в classic режиме отсутствие h
приводит к runtime error.
Комбинация jsxFactory и jsx: 'automatic'
приводит к игнорированию части настроек.
Внутренне процесс выглядит следующим образом:
jsxImportSource)Эта модель делает Esbuild быстрым по сравнению с многостадийными трансформерами.
Фрагменты:
<>
<A />
<B />
</>
в classic режиме:
Fragment(null, A(), B());
в automatic режиме:
import { Fragment } from "runtime";
jsx(Fragment, {}, A(), B());
При масштабировании приложений важную роль играет единообразие runtime:
jsxImportSourceEsbuild компилирует каждый файл независимо, поэтому несогласованность настроек приводит к неоднородному output.
Разные части приложения могут использовать разные JSX runtime при условии изоляции сборок.
При серверной сборке JSX трансформируется аналогично, но runtime заменяется на серверные реализации render функций.
Esbuild позволяет собирать UI-библиотеки, где JSX остаётся входным синтаксисом, а output содержит только runtime-агностичные вызовы.