### Роль `@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`, но с более агрессивной оптимизацией модульности на уровне импорта.