Структура возвращаемого объекта: code, map

Большинство API SWC в JavaScript, включая @swc/core, возвращают результат трансформации в виде объекта с фиксированной структурой. Основные поля:

  • code — итоговый JavaScript-код после трансформации
  • map — source map, описывающая соответствие исходного и сгенерированного кода

Дополнительно в некоторых режимах могут присутствовать вспомогательные поля (например, warnings), но базовая и наиболее используемая форма результата ограничивается именно парой code и map.


Поле code

Поле code содержит строку с результатом компиляции или трансформации исходного кода.

Характеристики code

  • Всегда возвращается как string

  • Представляет собой:

    • транспилированный JavaScript (например, TypeScript → JS)
    • или оптимизированный код после minify
    • или преобразованный код после применения plugins (JSX, decorators и т.д.)
  • Полностью готов к выполнению в JavaScript-движке

Пример структуры

{
  code: "const add = (a, b) => a + b;",
  map: null
}

Особенности генерации

В зависимости от конфигурации SWC:

  • jsc.target влияет на уровень трансформации синтаксиса
  • minify изменяет структуру и длину кода
  • sourceMaps определяет наличие и формат map

При включённой минификации code может содержать:

  • переименованные идентификаторы
  • удалённые пробелы и комментарии
  • инлайн-оптимизации выражений

Поле map

Поле map содержит информацию для сопоставления результирующего кода с исходным. Это реализация Source Map Specification, используемая всеми современными инструментами сборки.

Назначение map

Source map позволяет:

  • отлаживать трансформированный код
  • видеть оригинальные файлы в DevTools
  • корректно отображать ошибки (stack trace mapping)

Формат map

SWC может возвращать map в двух основных формах:

  1. Строка JSON

Наиболее распространённый вариант:

{
  code: "const x = 1;",
  map: "{\"version\":3,\"sources\":[\"input.js\"],\"names\":[],\"mappings\":\"AAAA\"}"
}

  1. Объект

При некоторых конфигурациях или внутренней обработке:

{
  code: "const x = 1;",
  map: {
 version: 3,
 sources: ["input.js"],
 names: [],
 mappings: "AAAA",
 file: "output.js",
 sourcesContent: ["const x = 1;"]
  }
}

Структура Source Map

Типичный объект map включает следующие поля:

version

Версия спецификации source map. Почти всегда:

3

sources

Массив исходных файлов:

sources: ["input.ts"]

names

Список идентификаторов, участвующих в маппинге:

names: ["add", "result"]

mappings

Основная часть source map — закодированная строка соответствий:

"AAAA,SAASA,GAAG,CAACC,CAAD,EAAGC,CAAH"

Это VLQ-кодированная структура, описывающая:

  • позицию в выходном коде
  • соответствующую позицию в исходном коде
  • индексы файлов и символов

sourcesContent

Опциональное поле, содержащее исходный код:

sourcesContent: [
  "export const add = (a, b) => a + b;"
]

file

Имя результирующего файла:

file: "output.js"

Взаимодействие code и map

Оба поля формируют единый механизм отладки:

  • code — исполняемый результат
  • map — обратная проекция к исходнику

Связь между ними строится построчно и посимвольно. Каждый сегмент mappings указывает:

  • индекс строки в code
  • индекс колонки
  • источник в sources
  • позицию в оригинальном файле

Поведение в transform и transformSync

transformSync

Синхронный API:

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


const result = transformSync("const x = 1;", { jsc: { target: "es2020"
}, sourceMaps: true });

Возвращает:

{
  code: "...",
  map: "..."
}

transform (асинхронный)

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

const result = await transform("const x = 1;", {
  jsc: {
    target: "es2020"
  },
  sourceMaps: true
});

Формат результата аналогичен, но обёрнут в Promise.


Влияние конфигурации на map

sourceMaps: true

Генерирует внешний source map.

sourceMaps: “inline”

Встраивает map внутрь code:

code: "const x = 1;//
map: null

sourceMaps: false

Полностью отключает генерацию:

{
  code: "...",
  map: null
}

Особенности сериализации map

При передаче через API или сохранении в файл возникают важные нюансы:

Строковый формат

Требует парсинга:

JSON.parse(result.map)

Объектный формат

Удобен для дальнейшей модификации:

  • добавление sourcesContent
  • изменение file
  • объединение нескольких sourcemap

Типичные сценарии использования структуры code / map

Интеграция с bundler

Vite / Webpack / esbuild-пайплайны используют map для цепочки трансформаций.

Каждый этап:

  1. принимает map предыдущего шага
  2. трансформирует код
  3. обновляет source map

Отладка в браузере

DevTools используют map для отображения оригинального TypeScript/JSX кода вместо сгенерированного JavaScript.


Постобработка кода

При анализе AST-пайплайнов:

  • code используется как конечный артефакт
  • map сохраняется для диагностики ошибок

Практические нюансы работы

Потеря синхронизации

При ручной модификации code без обновления map:

  • DevTools показывают неверные строки
  • stack traces становятся некорректными

Большие source maps

При сборке монорепозиториев:

  • sourcesContent может значительно увеличивать размер map
  • часто отключается для production

Производительность

Генерация map увеличивает:

  • время трансформации
  • использование памяти

Особенно заметно при:

  • minify больших файлов
  • обработке TypeScript проектов

Совместимость с инструментами

SWC map совместим с:

  • Chrome DevTools
  • Firefox Debugger
  • Node.js stack traces
  • bundler pipelines (Webpack, Rollup, Vite)

Поведение при minify

При включённой минификации структура сохраняется:

{
  code: "const a=1,b=2;console.log(a+b);",
  map: "{...}"
}

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

  • уменьшенное количество names
  • более плотные mappings
  • удалённые исходные пробелы и переносы

Итоговая модель данных результата SWC

Концептуально результат можно представить как:

TransformationResult
 ├── code: string
 └── map: string | object | null

где map является необязательной, но критически важной частью при разработке и отладке сложных JavaScript-приложений.