automatic runtimeПри использовании JSX-трансформации современного формата
(automatic) код JSX больше не требует явного подключения
React в каждом файле. Вместо этого компилятор преобразует
JSX-выражения в вызовы функций из специального runtime-модуля.
JSX:
const element = <div>Hello</div>;
После трансформации:
import { jsx as _jsx } from "react/jsx-runtime";
const element = _jsx("div", { children: "Hello" });
Ключевая особенность заключается в том, что источник этих функций
(jsx, jsxs, Fragment) задаётся
через параметр runtime-библиотеки. Именно за это отвечает
jsxImportSource.
jsxImportSourcejsxImportSource определяет модуль, из которого Esbuild
импортирует функции JSX runtime при использовании режима
automatic.
По умолчанию используется:
react
То есть:
import { jsx } from "react/jsx-runtime";
Если изменить источник, меняется сам модуль, откуда берётся runtime:
react/jsx-runtimepreact/jsx-runtime@emotion/react/jsx-runtimejsx: automaticПараметр jsxImportSource имеет смысл только при
включённой автоматической трансформации:
jsx: "automatic"
Если используется classic runtime, то
jsxImportSource игнорируется, так как код генерируется
через React.createElement.
Пример настройки через API:
import * as esbuild from "esbuild";
await esbuild.build({
entryPoints: ["src/index.jsx"],
bundle: true,
outfile: "dist/bundle.js",
jsx: "automatic",
jsxImportSource: "react"
});
В этом случае JSX:
const App = () => <h1>Title</h1>;
преобразуется в:
import { jsx as _jsx } from "react/jsx-runtime";
const App = () => _jsx("h1", { children: "Title" });
await esbuild.build({
entryPoints: ["src/app.jsx"],
bundle: true,
outfile: "dist/app.js",
jsx: "automatic",
jsxImportSource: "preact"
});
Результат трансформации:
import { jsx as _jsx } from "preact/jsx-runtime";
const App = () => _jsx("div", { children: "Hello Preact" });
jsxImportSource: "@emotion/react"
import { jsx as _jsx } from "@emotion/react/jsx-runtime";
Это позволяет автоматически подключать поддержку css
пропсов без дополнительного импорта jsx.
При использовании CLI можно передать опцию через флаг:
esbuild src/index.jsx --bundle --outfile=dist/bundle.js --jsx=automatic --jsx-import-source=react
Важно: имя флага соответствует camelCase-параметру API.
В TypeScript существует аналогичная настройка:
{
"compilerOptions": {
"jsx": "react-jsx",
"jsxImportSource": "react"
}
}
Однако при использовании Esbuild TypeScript не выполняет трансформацию JSX, если включена сборка через Esbuild. В этом случае:
jsxImportSource должен быть синхронизирован между
tsconfig и esbuild-конфигомjsxImportSource от jsxFactoryСуществуют два разных подхода к генерации JSX:
jsx: "classic",
jsxFactory: "React.createElement"
Результат:
React.createElement("div", null, "text");
jsx: "automatic",
jsxImportSource: "react"
Результат:
import { jsx } from "react/jsx-runtime";
Ключевое различие:
jsxFactory управляет функцией создания элементов в
classic-режимеjsxImportSource управляет модулем runtime в
automatic-режимеПри использовании automatic runtime Fragment также импортируется из runtime-модуля:
import { Fragment as _Fragment } from "react/jsx-runtime";
Пример JSX:
<>
<span>A</span>
<span>B</span>
</>
После трансформации:
import { Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
const App = () =>
_jsxs(_Fragment, {
children: [
_jsx("span", { children: "A" }),
_jsx("span", { children: "B" })
]
});
В сложных сборках возможно разделение по разным источникам:
react@emotion/reactНо Esbuild применяет jsxImportSource глобально для
текущей сборки, поэтому для гибридных проектов требуется:
Если выбран неверный jsxImportSource, например:
jsxImportSource: "unknown-lib"
результатом будет генерация:
import { jsx } from "unknown-lib/jsx-runtime";
и ошибка возникнет уже на этапе выполнения, а не компиляции, так как Esbuild не проверяет наличие модулей.
Использование automatic runtime с jsxImportSource даёт
следующие эффекты:
import React from "react"jsx/jsxsОсобенно заметно при больших приложениях с тысячами JSX-узлов.
Esbuild позволяет комбинировать:
В таких случаях jsxImportSource становится частью общей
цепочки трансформации AST, определяя базовый источник функций JSX
runtime до применения дополнительных плагинов.
reactpreactРезультат: некорректные импорты jsx-runtime
jsx: "classic",
jsxImportSource: "react"
jsxImportSource игнорируется, что приводит к
неожиданному React.createElement.
Например:
npm install react
без него генерация кода корректна, но выполнение завершится ошибкой.
В монорепозиториях часто используется единая настройка:
jsxImportSourceПри этом возможна переопределяемость на уровне отдельных build-скриптов для пакетов UI и приложений.
При включённой настройке:
jsx: "automatic",
jsxImportSource: "react"
Esbuild следует следующему принципу:
jsxImportSourcejsx/jsxs/FragmentЭтот механизм делает jsxImportSource центральным
элементом управления JSX-экосистемой внутри Esbuild, определяющим не
только синтаксис, но и архитектуру взаимодействия с
runtime-библиотеками.