Поле jsc.externalHelpers
### Поле `jsc.externalHelpers`
#### Назначение и роль в архитектуре SWC
В процессе трансформации JavaScript-кода компилятор SWC генерирует вспомогательные функции (helpers), которые обеспечивают корректную работу современных синтаксических конструкций после транспиляции в более старые версии ECMAScript. Эти вспомогательные функции могут включаться непосредственно в каждый выходной файл или выноситься в отдельную общую зависимость.
Поле `jsc.externalHelpers` управляет стратегией использования этих helper-функций: инлайн-генерацией или внешним подключением через единый runtime-пакет.
Ключевая идея:
* при `false` helpers вставляются в каждый файл отдельно;
* при `true` используется общий пакет `@swc/helpers`, который подключается как внешняя зависимость.
---
#### Поведение при значении `false`
По умолчанию SWC может генерировать вспомогательные функции прямо в каждый модуль, где они требуются. Это приводит к следующей модели:
* каждый файл содержит собственные копии `_extends`, `_classCallCheck`, `_asyncToGenerator` и других helper-функций;
* отсутствует внешняя зависимость;
* упрощается запуск без дополнительных пакетов.
Однако такая модель имеет последствия:
* увеличение итогового размера бандла;
* дублирование кода между модулями;
* ухудшение эффективности кеширования;
* рост времени загрузки в браузере.
Пример результата при инлайн-режиме:
```js
function _extends() {
_extends = Object.assign || function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
};
return _extends.apply(this, arguments);
}
```
Этот код может повторяться в десятках файлов.
---
#### Поведение при значении `true`
При включении:
```json
{
"jsc": {
"externalHelpers": true
}
}
```
SWC перестаёт внедрять вспомогательные функции внутрь каждого файла и вместо этого использует импорт из пакета:
```js
import { _extends } from "@swc/helpers";
```
или аналогичных внутренних модулей `@swc/helpers`.
---
#### Роль пакета `@swc/helpers`
Пакет `@swc/helpers` является централизованным набором runtime-функций, необходимых для корректной работы транспилированного кода.
Он включает реализации:
* классовых helper-ов (`_classCallCheck`, `_createClass`);
* async/await преобразований (`_asyncToGenerator`);
* spread-операторов (`_extends`);
* генераторов и итераторов;
* некоторых утилит для Babel-совместимости.
Использование внешнего пакета позволяет:
* устранить дублирование runtime-кода;
* улучшить кеширование на уровне браузера и CDN;
* уменьшить общий размер JavaScript-бандла;
* унифицировать поведение между файлами и пакетами.
---
#### Принцип работы трансформации
При включённом `externalHelpers` SWC выполняет следующие шаги:
1. Анализирует AST и выявляет необходимость helper-функций.
2. Проверяет наличие соответствующих импортов.
3. Заменяет встроенные реализации на импортируемые символы.
4. Добавляет импорт из `@swc/helpers` в начало файла при необходимости.
Пример до трансформации:
```js
class A {}
```
После трансформации:
```js
import { _classCallCheck } from "@swc/helpers/_/_class_call_check";
var A = function A() {
_classCallCheck(this, A);
};
```
---
#### Особенности модульного импорта
SWC не всегда импортирует весь пакет целиком. Вместо этого используется granular-import подход:
* каждый helper импортируется отдельно;
* пути могут быть точечными (`@swc/helpers/_/_extends`);
* обеспечивается tree-shaking на уровне bundler-а.
Это снижает избыточность даже при использовании внешней зависимости.
---
#### Совместимость с bundler-ами
Использование `externalHelpers` требует корректной работы сборщика:
##### Webpack
Webpack корректно обрабатывает `@swc/helpers` как обычный npm-пакет. При этом:
* возможна дедупликация через resolve.alias;
* поддерживается tree-shaking в production mode.
##### Vite
Vite обрабатывает такие импорты через ESBuild prebundle:
* `@swc/helpers` попадает в оптимизированные зависимости;
* уменьшается количество HTTP-запросов за счёт бандлинга.
##### Rollup
Rollup эффективно трясёт дерево зависимостей:
* helper-функции включаются только при использовании;
* возможна агрессивная оптимизация размера.
---
#### Влияние на размер бандла
Разница между режимами особенно заметна в крупных проектах.
##### Без externalHelpers
* каждый модуль содержит дублирующие runtime-функции;
* увеличение размера пропорционально числу файлов;
* особенно критично при микрофронтендах.
##### С externalHelpers
* helpers загружаются один раз;
* размер растёт только за счёт фактического использования функций;
* уменьшается общий JS payload.
---
#### Проблемы и ограничения
Несмотря на преимущества, использование `externalHelpers` вводит ряд требований:
##### 1. Необходимость зависимости
Проект обязан включать:
```bash
npm install @swc/helpers
```
Отсутствие пакета приводит к runtime-ошибкам импорта.
---
##### 2. Версионные несоответствия
Разные версии SWC и `@swc/helpers` могут:
* изменять сигнатуры helper-функций;
* добавлять новые импорты;
* изменять пути модулей.
Это требует синхронизации версий в монорепозиториях.
---
##### 3. Особенности SSR
В Node.js окружении:
* external helpers увеличивают число импортов;
* возможна задержка cold start;
* требуется корректная резолюция ESM/CJS.
---
#### Монорепозитории и повторное использование
В монорепозиториях `externalHelpers` часто используется совместно с workspace-зависимостями.
Преимущества:
* единый runtime для всех пакетов;
* отсутствие дублирования helpers между пакетами;
* упрощённый контроль версий.
Типичная конфигурация:
```json
{
"jsc": {
"externalHelpers": true
}
}
```
и единый `@swc/helpers` в корне workspace.
---
#### Взаимодействие с другими опциями SWC
`externalHelpers` тесно связан с другими параметрами:
* `jsc.target` — влияет на набор необходимых helpers;
* `module.type` — определяет формат импортов;
* `minify` — может удалять неиспользуемые helpers;
* `keepClassNames` — снижает количество генераций class helpers.
Чем старее target (например, ES5), тем больше helpers требуется.
---
#### Практическая модель выбора
Решение о включении опции определяется архитектурой:
* небольшие проекты → допустим inline-режим;
* библиотеки → предпочтителен external режим;
* крупные SPA → почти всегда externalHelpers;
* микрофронтенды → обязательное использование external runtime.
---
#### Влияние на повторное использование кода
External helpers создают единый слой абстракции:
* одинаковые трансформации используют одни и те же реализации;
* уменьшается вероятность расхождений между модулями;
* упрощается анализ и отладка транспилированного кода.
---
#### Поведение при tree-shaking
При корректной настройке bundler-а:
* неиспользуемые helpers исключаются;
* импортируются только реально задействованные функции;
* итоговый runtime минимизируется до фактического набора операций.
---
#### Типовые ошибки конфигурации
На практике встречаются следующие проблемы:
* отсутствие `@swc/helpers` в dependencies;
* смешивание external и inline режимов в разных пакетах;
* неправильная резолюция путей импорта;
* несовместимость с legacy bundler-ами без ESM поддержки.
Каждая из них приводит либо к дублированию, либо к runtime-ошибкам.
---
#### Поведение при миграции с Babel
При переходе с Babel на SWC:
* аналогом `@babel/plugin-transform-runtime` выступает `externalHelpers`;
* аналогом `@babel/runtime` является `@swc/helpers`;
* логика разделения runtime идентична.
Это упрощает миграцию крупных кодовых баз без изменения архитектуры импорта helpers.