Совместное использование @swc/helpers

### Роль `@swc/helpers` в трансформациях SWC При транспиляции современного JavaScript (TypeScript, JSX, class fields, async/await) компилятору требуется набор вспомогательных функций, реализующих низкоуровневое поведение языка в средах, где нативная поддержка отсутствует или неполна. SWC генерирует такие конструкции автоматически, и именно здесь появляется пакет `@swc/helpers`. Эти helpers представляют собой набор функций-«полифилов на уровне компиляции», которые заменяют встроенную логику трансформаций на переиспользуемые импорты вместо инлайна в каждом файле. --- ### Генерация helper-кода: встроенный режим и внешний пакет SWC поддерживает два основных режима работы с вспомогательными функциями: **1. Встроенная генерация (inline helpers)** При этом режиме каждый файл получает собственные копии вспомогательных функций. Например, при трансформации классов или async/await в каждый модуль могут быть добавлены функции вроде `_classCallCheck`, `_inherits`, `_asyncToGenerator`. Характеристика: * отсутствие внешних зависимостей * увеличение размера бандла * дублирование кода между модулями --- **2. Внешние helpers через `@swc/helpers`** При включении внешнего режима SWC заменяет встроенные функции импортами: ```js import { _classCallCheck } from "@swc/helpers/_/_class_call_check"; ``` Каждый helper становится импортируемым модулем из пакета `@swc/helpers`. Ключевая особенность: * единый источник реализации * возможность tree-shaking на уровне бандлера * уменьшение дублирования --- ### Конфигурация SWC для использования external helpers В SWC включение внешних helpers выполняется через опцию: ```json { "jsc": { "externalHelpers": true } } ``` После активации этого режима компилятор перестаёт инлайнить вспомогательные функции и заменяет их импортами из `@swc/helpers`. --- ### Структура пакета `@swc/helpers` Пакет организован модульно. Каждый helper вынесен в отдельный файл, например: * `@swc/helpers/_/_extends` * `@swc/helpers/_/_async_to_generator` * `@swc/helpers/_/_inherits` * `@swc/helpers/_/_class_call_check` Такой подход обеспечивает: * точечные импорты * корректную работу tree-shaking * совместимость с ESM и CJS окружениями --- ### Причины появления внешних helpers Основная проблема inline-стратегии — рост размера кода при масштабировании проекта. При компиляции большого набора модулей повторяются одинаковые реализации: * вспомогательные функции классов * обработка spread/rest * генераторы async/await * работа с `super` и прототипами Внешний пакет решает это через централизацию. --- ### Поведение при трансформации классов Пример исходного кода: ```ts class A { constructor(value) { this.value = value; } } ``` SWC с external helpers превращает это примерно в: ```js import { _classCallCheck } from "@swc/helpers/_/_class_call_check"; var A = function A(value) { _classCallCheck(this, A); this.value = value; }; ``` Без external helpers тот же код будет содержать встроенную реализацию `_classCallCheck`, повторяющуюся в каждом модуле. --- ### Async/await и генераторы Одним из наиболее тяжёлых с точки зрения трансформации является `async/await`. SWC использует helper вида `_async_to_generator`, который оборачивает генератор в Promise-совместимую функцию. С external helpers: ```js import { _async_to_generator } from "@swc/helpers/_/_async_to_generator"; function fetchData() { return _async_to_generator(function* () { const res = yield fetch("/api"); return res.json(); })(); } ``` Такой подход позволяет: * избежать дублирования runtime-обёрток * централизовать сложную логику обработки Promise * уменьшить размер итогового JS --- ### Связь с bundler’ами и tree-shaking Эффективность `@swc/helpers` сильно зависит от сборщика: #### ES Modules При использовании ESM каждый helper может быть вычищен tree-shaking’ом, если не используется: * Rollup * Vite * esbuild (в определённых режимах) * Webpack 5 (при правильной конфигурации) #### CommonJS В CJS tree-shaking ограничен, поэтому возможны ситуации, когда весь пакет попадает в бандл. --- ### Влияние на размер бандла Разница между inline и external подходом становится заметной в больших приложениях: **Inline helpers:** * рост дублируемого кода пропорционален числу модулей * особенно заметно при использовании классов и async функций **External helpers:** * код helpers загружается один раз * повторное использование через импорты * лучше работает кэширование на уровне браузера и CDN --- ### Взаимодействие с TypeScript и JSX `@swc/helpers` используется не только для классов и async, но и для: * spread/rest объектов * JSX трансформаций (в некоторых конфигурациях) * обработки наследования * Object.assign-подобных операций Например: ```tsx const el =
; ``` может трансформироваться с использованием helper вроде `_extends`. --- ### Версионная совместимость Критический аспект — синхронизация версий: * SWC compiler * `@swc/helpers` Несовпадение версий может привести к: * отсутствию нужных helper-функций * изменению сигнатур внутренних реализаций * ошибкам сборки в рантайме Практика стабильной сборки предполагает фиксирование версий или использование lockfile. --- ### Дублирование helpers при монорепозиториях В монорепозиториях (pnpm, yarn workspaces) возможна ситуация, когда: * разные пакеты используют разные версии `@swc/helpers` * bundler не дедуплицирует зависимости Это приводит к: * увеличению итогового бандла * дублированию runtime функций Решение достигается через: * hoisting зависимостей * принудительное выравнивание версий * aliasing в bundler конфигурации --- ### Практические сценарии использования #### Библиотеки При создании npm-библиотек использование external helpers часто предпочтительно: * снижает размер distributed bundle * исключает повторение runtime кода * упрощает поддержку #### Приложения В приложениях выбор зависит от архитектуры: * маленькие проекты — inline проще * крупные SPA — external эффективнее --- ### Ограничения подхода external helpers Несмотря на преимущества, присутствуют ограничения: * дополнительный runtime dependency * необходимость контроля версии * потенциальная сложность диагностики при ошибках сборки * зависимость от корректной работы bundler tree-shaking --- ### Влияние на архитектуру компиляции SWC Использование `@swc/helpers` отражает общий подход SWC: * минимизация дублирования * перенос runtime логики в отдельный слой * разделение компиляции и исполнения * совместимость с экосистемой JS bundlers Это сближает SWC с подходом Babel + `@babel/runtime`, но с более агрессивной оптимизацией модульности на уровне импорта.