Настройка трансформаций: transform

Трансформация в SWC строится вокруг этапа JSC (JavaScript Compiler), который отвечает за преобразование современного JavaScript и TypeScript в совместимый с целевой средой код. Основной принцип заключается в разделении конфигурации на уровни: синтаксический анализ, трансформации AST и генерация кода.

Ключевая особенность SWC — высокая скорость за счёт реализации на Rust и строгого разделения трансформационных стадий.


Базовая структура конфигурации transform

Конфигурация трансформаций задаётся через поле jsc.transform в .swcrc или при использовании @swc/core.

{
  "jsc": {
    "parser": {
      "syntax": "typescript"
    },
    "transform": {
      "react": {
        "runtime": "automatic"
      }
    }
  }
}

Основная логика трансформаций сосредоточена в объекте:

  • jsc.transform.react
  • jsc.transform.optimizer
  • jsc.transform.regenerator
  • jsc.transform.legacyDecorator
  • jsc.transform.decoratorMetadata

Трансформация React-кода

SWC поддерживает преобразование JSX через встроенный трансформер React.

Основные параметры

  • runtime — способ обработки JSX
  • importSource — источник JSX функций
  • development — включение dev-режима
  • refresh — поддержка Fast Refresh
{
  "jsc": {
    "transform": {
      "react": {
        "runtime": "automatic",
        "importSource": "react",
        "development": false,
        "refresh": false
      }
    }
  }
}

Automatic runtime

При runtime: “automatic” SWC автоматически вставляет импорты функций JSX:

Исходный код:

const App = () => <div>Hello</div>;

Результат:

import { jsx as _jsx } from "react/jsx-runtime";

const App = () => _jsx("div", { children: "Hello" });

Важно: необходимость ручного импорта React отпадает.


TypeScript трансформация

SWC не выполняет типизацию, а только удаляет типы и преобразует синтаксис.

{
  "jsc": {
    "parser": {
      "syntax": "typescript",
      "tsx": true
    }
  }
}

Поддерживаются:

  • interface, type
  • enum
  • namespace
  • generics (удаляются без изменений runtime)
  • decorators (через отдельный флаг)

Пример:

interface User {
  name: string;
}

const user: User = { name: "Alex" };

Результат:

const user = { name: "Alex" };

Настройка целевой среды (target)

Поле env.target определяет уровень ECMAScript, к которому приводится код.

{
  "env": {
    "target": "es2018"
  }
}

Возможные значения:

  • es5
  • es2015
  • es2017
  • es2020
  • es2022
  • esnext

Влияние target

SWC автоматически включает или исключает трансформации:

  • стрелочные функции → function
  • const/let → var (для ES5)
  • async/await → regenerator runtime (если включено)
  • классы → ES5-конструкторы (при необходимости)

Regenerator и async/await

Асинхронные функции требуют отдельного трансформера:

{
  "jsc": {
    "transform": {
      "regenerator": true
    }
  }
}

Пример:

async function load() {
  const data = await fetch("/api");
  return data.json();
}

Результат при ES5 target:

function load() {
  return _async_to_generator(function* () {
    const data = yield fetch("/api");
    return data.json();
  })();
}

Особенность: SWC использует генераторную модель вместо state machine как у некоторых других компиляторов.


Поддержка декораторов

SWC поддерживает два режима декораторов:

  • legacy (TypeScript старого формата)
  • proposal (TC39 stage 3)

Legacy decorators

{
  "jsc": {
    "transform": {
      "legacyDecorator": true
    }
  }
}

Пример:

function readonly(target, key, descriptor) {
  descriptor.writable = false;
}

class Test {
  @readonly
  method() {}
}

Decorator metadata

Дополнительная опция:

{
  "jsc": {
    "transform": {
      "decoratorMetadata": true
    }
  }
}

Используется для reflection API:

import "reflect-metadata";

Оптимизация кода

SWC включает встроенный optimizer на уровне AST.

{
  "jsc": {
    "transform": {
      "optimizer": {
        "globals": {
          "vars": {
            "DEBUG": false
          }
        }
      }
    }
  }
}

Возможности optimizer

  • свёртка констант
  • удаление dead code
  • инлайнинг переменных
  • упрощение условий

Пример:

if (false) {
  console.log("never");
}

Результат:

// удалено полностью

Трансформация модулей

SWC поддерживает преобразование ES Modules в CommonJS и другие форматы.

{
  "module": {
    "type": "commonjs"
  }
}

Варианты:

  • commonjs
  • amd
  • umd
  • es6 (без изменений)
  • systemjs

Пример преобразования

import fs from "fs";

export const read = () => fs.readFileSync("a.txt");

Результат CommonJS:

const fs = require("fs");

exports.read = () => fs.readFileSync("a.txt");

Программная настройка transform API

Помимо .swcrc, трансформации задаются через @swc/core.

import { transform } from "@swc/core";

const output = await transform(code, {
  jsc: {
    parser: {
      syntax: "typescript",
      tsx: true
    },
    transform: {
      react: {
        runtime: "automatic"
      }
    }
  }
});

Основные параметры API

  • filename
  • sourceMaps
  • isModule
  • minify
  • jsc

Source maps и трансформации

При включении source maps SWC связывает трансформированный код с оригинальным AST.

{
  "sourceMaps": true,
  "inlineSourcesContent": true
}

Особенности:

  • точное сопоставление строк
  • поддержка JSX и TS
  • корректная работа с nested transforms

Влияние parser на transform

Трансформации напрямую зависят от конфигурации парсера:

{
  "jsc": {
    "parser": {
      "syntax": "ecmascript",
      "jsx": true,
      "dynamicImport": true
    }
  }
}

Связь этапов

  1. parser формирует AST
  2. transform модифицирует AST
  3. codegen генерирует JS

Ошибка в parser полностью блокирует transform этап.


Порядок выполнения трансформаций

SWC применяет трансформации в фиксированном порядке:

  1. JSX transform
  2. TypeScript stripping
  3. Decorators
  4. Module transform
  5. Regenerator
  6. Optimizer

Порядок важен, так как некоторые трансформации зависят от структуры AST после предыдущих шагов.


Типичные конфигурации трансформаций

Современный frontend (React + TS)

{
  "jsc": {
    "parser": {
      "syntax": "typescript",
      "tsx": true
    },
    "transform": {
      "react": {
        "runtime": "automatic",
        "refresh": true
      }
    }
  }
}

Legacy поддержка браузеров

{
  "env": {
    "target": "es5"
  },
  "jsc": {
    "transform": {
      "regenerator": true
    }
  },
  "module": {
    "type": "commonjs"
  }
}

Минимальная конфигурация без трансформаций

{
  "jsc": {
    "parser": {
      "syntax": "ecmascript"
    }
  }
}

Особенности поведения transform слоя

  • трансформации не изменяют семантику типов
  • AST модифицируется иммутабельно на уровне проходов
  • большинство оптимизаций являются локальными
  • часть трансформаций зависит от target и module

Ключевой принцип: transform слой не интерпретирует код, а лишь переписывает структуру дерева синтаксиса.