Параметр importSource в SWC относится к настройке
трансформации JSX и определяет, из какого модуля будет импортироваться
JSX runtime при использовании автоматического режима JSX. Он напрямую
влияет на то, как компилятор переписывает JSX-выражения в JavaScript-код
и какие функции будут использованы для создания элементов.
В современном JSX-трансформе (React 17+ и аналогичных реализациях)
используется так называемый automatic runtime, при котором нет
необходимости явно импортировать React в каждом файле.
Вместо этого SWC генерирует импорты функций вроде jsx,
jsxs или jsxDEV из заданного runtime-модуля.
Именно выбор этого модуля и контролируется через
importSource.
JSX до компиляции:
const App = () => <div>Hello</div>;
После трансформации с runtime react:
import { jsx as _jsx } from "react/jsx-runtime";
const App = () => _jsx("div", { children: "Hello" });
Если указан другой importSource, например
preact, результат будет отличаться:
import { jsx as _jsx } from "preact/jsx-runtime";
const App = () => _jsx("div", { children: "Hello" });
Таким образом, importSource определяет базовый источник
JSX-функций.
В SWC параметр задаётся внутри секции jsc.transform.react.
Пример конфигурации .swcrc:
{
"jsc": {
"parser": {
"syntax": "typescript",
"tsx": true
},
"transform": {
"react": {
"runtime": "automatic",
"importSource": "react"
}
}
}
}
Здесь:
runtime: “automatic” включает новый JSX transform
importSource определяет пакет, из которого берутся
JSX-функции
Если значение не указано, используется стандартное поведение,
эквивалентное “react”.
JSX runtime представляет собой набор функций, отвечающих за создание элементов. В зависимости от среды они могут различаться:
react/jsx-runtime
preact/jsx-runtime
SWC формирует импорт автоматически:
import { jsx } from `${importSource}/jsx-runtime`;
и аналогично для jsxDEV в dev-режиме.
importSource имеет смысл только при включённом:
"runtime": "automatic"
При классическом runtime:
"runtime": "classic"
JSX трансформируется в вызовы React.createElement, и
importSource полностью игнорируется.
Пример classic:
import React from "react";
const App = () => React.createElement("div", null, "Hello");
Preact использует собственный runtime:
{
"jsc": {
"transform": {
"react": {
"runtime": "automatic",
"importSource": "preact"
}
}
}
}
Результат трансформации:
import { jsx as _jsx } from "preact/jsx-runtime";
Особенность заключается в том, что Preact предоставляет API, совместимый с React JSX, но с меньшим размером и иной реализацией виртуального DOM.
CSS-in-JS библиотеки используют importSource для перехвата
JSX.
Пример:
{
"jsc": {
"transform": {
"react": {
"runtime": "automatic",
"importSource": "@emotion/react"
}
}
}
}
Тогда JSX компилируется в вызовы Emotion runtime:
import { jsx } from "@emotion/react/jsx-runtime";
Это позволяет внедрять обработку CSS-пропсов на уровне JSX без Babel-плагинов.
В TypeScript существует аналогичная настройка:
{
"compilerOptions": {
"jsx": "react-jsx",
"jsxImportSource": "preact"
}
}
Различие:
jsxImportSource — TypeScript уровень
importSource — SWC уровень
При использовании SWC TypeScript настройка может игнорироваться, если трансформация JSX полностью делегирована SWC.
SWC автоматически переключает используемые функции в зависимости от окружения:
jsxDEV
jsx
jsxs
Пример dev:
import { jsxDEV as _jsxDEV } from "react/jsx-dev-runtime";
const App = () =>
_jsxDEV("div", { children: "Hello" }, undefined, false, undefined, this);
importSource влияет и на dev-runtime:
import { jsxDEV } from "preact/jsx-dev-runtime";
Выбор importSource может существенно влиять на итоговый
размер сборки:
Особенно это заметно при использовании Preact или специализированных runtime-библиотек.
React начиная с 17 версии поддерживает automatic runtime:
import { jsx } from "react/jsx-runtime";
SWC полностью повторяет эту модель.
Для React 18+ дополнительная настройка не требуется, но
importSource остаётся полезным для:
{
"jsc": {
"transform": {
"react": {
"runtime": "automatic"
}
}
}
}
{
"jsc": {
"transform": {
"react": {
"runtime": "automatic",
"importSource": "react"
}
}
}
}
{
"jsc": {
"transform": {
"react": {
"runtime": "automatic",
"importSource": "preact"
}
}
}
}
На серверной стороне JSX runtime может отличаться:
react/jsx-runtime vs
react/jsx-dev-runtime)
importSource остаётся одинаковым
jsx-runtime vs
jsx-dev-runtime)
importSource не влияет на runtime поведение, только на
импорт
Пример ошибки:
Cannot find module &
Механика генерации импортов внутри SWC
SWC внутренне строит AST и заменяет JSX следующим образом:
-
анализирует наличие JSX
-
проверяет
runtime: automatic
-
берёт значение
importSource
-
формирует путь
${importSource}/jsx-runtime</code></li>
<li>генерирует named import функций <code>jsx</code>,
<code>jsxs</code>,
<code>Fragment</code></li>
</ol>
<p>Псевдологика:</p>
<pre class="text"><code>if (runtime ===
"automatic") {
source = `${importSource}/jsx-runtime` }
Fragment также импортируется из того же источника:
import { Fragment } from "react/jsx-runtime";
или при кастомном source:
import { Fragment } from "preact/jsx-runtime";
Это важно для корректной работы JSX без лишних DOM-узлов.
В монорепозиториях часто требуется поддержка нескольких JSX runtime:
В таких случаях importSource становится ключевым механизмом
изоляции трансформации, позволяя каждому пакету компилироваться под свой
runtime без конфликтов.
Если параметр не указан:
“react” как значение по умолчанию
react/jsx-runtime
Это обеспечивает совместимость «из коробки» для большинства проектов без дополнительных настроек