Архитектура плагинов SWC построена вокруг идеи компилятора как набора
изолированных этапов трансформации синтаксического дерева (AST), где
каждый этап может быть расширен или заменён через строго определённые
точки расширения. Основная цель такой модели — сохранить высокую
производительность Rust-ядра при возможности кастомизации поведения
компиляции на уровне JavaScript/TypeScript проектов.
Плагинная система SWC не является монолитной. Она разделена на несколько
слоёв:
-
ядро компилятора (парсер, трансформер, генератор кода)
-
слой промежуточного представления (AST)
-
система проходов (passes)
-
интерфейсы расширений (plugins)
Ключевой принцип — плагины не вмешиваются напрямую в внутреннюю
логику компилятора, а работают через стандартизированные
операции над AST.
Позиция плагинов в компиляционном пайплайне
Общий пайплайн SWC можно представить как последовательность стадий:
-
Парсинг исходного кода
-
исходный код → AST
-
учитываются ECMAScript и TypeScript синтаксические расширения
-
Трансформации AST
-
применение встроенных оптимизаций
-
применение пользовательских плагинов
-
выполнение preset-преобразований (например, TypeScript → JavaScript)
-
Генерация кода
-
AST → строковый JavaScript
-
минификация (если включена)
Плагины встраиваются именно во второй этап, формируя цепочку
преобразований. Каждый плагин получает AST, модифицирует его и
возвращает изменённую структуру.
AST как основа плагинной системы
SWC использует структурированный AST, близкий по модели к ESTree, но с
расширениями под Rust-реализацию.
Ключевые особенности:
-
строгая типизация узлов (Rust enums + structs)
-
отсутствие динамических полей
-
иммутабельная модель обработки (частично копирующая)
-
оптимизация под zero-cost abstractions
Типичный узел AST может представлять выражение, декларацию или оператор.
Плагины работают через обход этого дерева.
Visitor-модель и обход дерева
Основной механизм модификации AST в SWC — паттерн
Visitor.
Каждый плагин реализует набор методов, соответствующих типам узлов:
-
visit_module
-
visit_function
-
visit_expression
-
visit_statement
Обход дерева происходит рекурсивно:
-
вход в узел
-
обработка дочерних узлов
-
возможная модификация текущего узла
-
возврат результата
Особенности реализации Visitor в SWC
-
обход оптимизирован на уровне Rust (без динамической диспетчеризации
там, где это возможно)
-
использование макросов для генерации boilerplate-кода
-
минимизация аллокаций при трансформациях
-
возможность раннего выхода из посещения поддеревьев
Типы плагинов SWC
Архитектура расширений не ограничивается одним типом плагина. В
зависимости от уровня интеграции выделяются несколько классов.
Наиболее распространённый тип.
Функции:
-
изменение структуры кода
-
переписывание выражений
-
внедрение полифиллов
-
оптимизация выражений
Примеры задач:
-
преобразование JSX
-
удаление console.log
-
инлайнинг констант
Особенность: работают исключительно на уровне AST, не затрагивая
лексический анализ.
Parser Extensions
Менее распространённый, но более низкоуровневый тип.
Функции:
-
расширение синтаксиса языка
-
поддержка нестандартных конструкций
-
изменение поведения парсера
Ограничение:
-
требует глубокой интеграции с Rust-ядром
-
сложнее в разработке и сопровождении
Resolver Plugins
Используются на этапе разрешения модулей.
Функции:
-
изменение правил импорта
-
кастомизация alias-резолвинга
-
обработка виртуальных модулей
Характерная особенность:
-
работают до трансформации AST
-
влияют на структуру зависимостей
Codegen Hooks (ограниченные расширения)
Финальный этап пайплайна.
Функции:
-
постобработка сгенерированного кода
-
форматирование
-
внедрение source maps
Ограничения:
-
минимальный доступ к AST
-
преимущественно текстовая стадия
WASM-плагины и изоляция выполнения
В экосистеме SWC значительная часть плагинов реализуется через
WebAssembly.
Причины выбора WASM:
-
безопасность выполнения стороннего кода
-
переносимость между средами Node.js и браузера
-
совместимость с Rust-инфраструктурой
-
предсказуемая производительность
Архитектура WASM-плагина
WASM-плагин состоит из:
-
скомпилированного модуля (.wasm)
-
JavaScript-обёртки
-
описания типов входных AST-структур
Поток выполнения:
-
SWC сериализует AST
-
передаёт его в WASM-модуль
-
модуль модифицирует структуру
-
результат десериализуется обратно в Rust AST
Ограничения WASM-слоя
Несмотря на гибкость, WASM-плагины имеют ограничения:
-
невозможность прямого доступа к памяти компилятора
-
необходимость сериализации AST
-
ограниченная работа с внешними API
-
дополнительный overhead на обмен данными
Эти ограничения компенсируются изоляцией и безопасностью исполнения.
Модель данных между ядром и плагинами
Передача данных между слоями осуществляется через строго определённые
структуры:
-
JSON-подобные промежуточные представления
-
бинарные сериализации AST
-
Rust-совместимые типы через FFI
Ключевой принцип — минимизация потерь структуры AST при
сериализации.
Цепочка трансформаций (plugin pipeline)
Плагинная система SWC организована как последовательность проходов:
AST → Plugin 1 → AST → Plugin 2 → AST → Plugin N → AST
Каждый плагин:
-
получает входной AST
-
возвращает новый AST
-
не имеет глобального состояния (в идеале)
Особенности выполнения:
-
порядок плагинов критичен
-
некоторые плагины могут изменять поведение последующих
-
возможна оптимизация цепочки (fusion passes)
Система пресетов и композиция плагинов
SWC поддерживает группировку трансформаций в пресеты.
Пресет — это:
-
набор плагинов
-
конфигурация порядка выполнения
-
предустановленные оптимизации
Преимущества:
-
стандартизация пайплайнов (например, React, TypeScript)
-
повторное использование конфигураций
-
упрощение сборки проектов
Производительность и zero-cost подход
Плагинная архитектура SWC проектируется с учётом производительности
компилятора как критического инструмента.
Основные стратегии:
-
минимизация динамической диспетчеризации
-
использование Rust enum вместо object-based AST
-
избегание глубокого копирования дерева
-
оптимизация проходов Visitor
-
inline-операции там, где возможно
Ошибки и модель диагностики в плагинах
Плагины могут возвращать ошибки на разных этапах:
-
синтаксические (на этапе парсинга)
-
трансформационные (некорректный AST)
-
резолвинга модулей
Система ошибок:
-
типизированные Rust error enums
-
переносимые сообщения в JS-слой
-
привязка к узлам AST (source mapping)
Безопасность плагинной архитектуры
Безопасность обеспечивается несколькими уровнями:
-
изоляция WASM
-
отсутствие прямого доступа к файловой системе
-
ограниченные API взаимодействия
-
контроль времени выполнения
Дополнительно:
-
плагины не могут изменять ядро компилятора
-
отсутствует возможность перехвата глобального состояния без явного API
Расширяемость и эволюция модели
Архитектура плагинов SWC развивается в сторону:
-
более строгой типизации AST между слоями
-
уменьшения стоимости сериализации
-
расширения WASM-интерфейсов
-
унификации трансформационных API
Текущая модель ориентирована на баланс между:
-
скоростью Rust-ядра
-
гибкостью JavaScript-экосистемы
-
безопасностью выполнения стороннего кода