Vitest и встроенная поддержка SWC

## Роль SWC в экосистеме Vitest **Vitest** представляет собой современный фреймворк тестирования для JavaScript и TypeScript, тесно интегрированный с экосистемой Vite. Одним из ключевых факторов производительности Vitest является скорость обработки исходного кода перед выполнением тестов. Для этой задачи может использоваться **SWC (Speedy Web Compiler)** — высокопроизводительный компилятор, написанный на языке Rust. SWC выполняет несколько важных функций: * трансформация современного JavaScript в более совместимый код; * компиляция TypeScript; * преобразование JSX и TSX; * обработка декораторов; * минификация; * генерация source maps. В контексте Vitest SWC чаще всего применяется как замена Babel или встроенному трансформеру TypeScript для ускорения подготовки тестируемого кода. --- ## Почему SWC используется вместе с Vitest При запуске тестов происходит несколько этапов: 1. Загрузка файлов. 2. Анализ зависимостей. 3. Трансформация исходного кода. 4. Выполнение тестов. 5. Формирование отчётов. На крупных проектах именно этап трансформации способен занимать значительную часть времени. Традиционные решения: | Инструмент | Язык реализации | | ------------------------- | --------------- | | Babel | JavaScript | | TypeScript Compiler (tsc) | TypeScript | | SWC | Rust | За счёт нативной реализации SWC зачастую обеспечивает ускорение в несколько раз по сравнению с Babel. Особенно заметна разница при: * тысячах тестовых файлов; * крупных монорепозиториях; * интенсивном использовании TypeScript; * проектах с React и JSX. --- ## Архитектура взаимодействия Vitest и SWC Упрощённая схема выглядит следующим образом: ```text Исходный файл │ ▼ SWC │ ▼ Трансформированный код │ ▼ Vitest │ ▼ Выполнение тестов ``` SWC отвечает исключительно за компиляцию и преобразование кода. Vitest занимается: * запуском тестов; * мокированием модулей; * отслеживанием изменений; * изоляцией окружения; * сбором результатов. Такое разделение обязанностей позволяет использовать максимально быстрый трансформер без изменения логики тестирования. --- ## Установка SWC Для большинства проектов требуется установить основные пакеты: ```bash npm install -D @swc/core ``` или ```bash yarn add -D @swc/core ``` или ```bash pnpm add -D @swc/core ``` Если используется React: ```bash npm install -D @swc/core @swc/helpers ``` Пакет `@swc/helpers` содержит вспомогательные функции, которые могут генерироваться во время трансформации кода. --- ## Конфигурация SWC через файл .swcrc SWC поддерживает отдельный конфигурационный файл. Пример: ```json { "jsc": { "parser": { "syntax": "typescript", "tsx": true }, "target": "es2022" }, "module": { "type": "es6" } } ``` Разберём параметры подробнее. ### parser.syntax Определяет тип входного кода. Для Jav * aScript: ```json { "syntax": "ecmascript" } ``` Для TypeScript: ```json { "syntax": "typescript" } ``` --- ### parser.tsx Активирует поддержку TSX. ```json { "tsx": true } ``` Необходим для React-приложений на TypeScript. --- ### parser.decorators Поддержка декораторов. ```json { "decorators": true } ``` Актуально для NestJS и других проектов, использующих экспериментальные возможности языка. --- ### jsc.target Указывает целевую версию JavaScript. Например: ```json { "target": "es2015" } ``` или ```json { "target": "es2022" } ``` Чем современнее целевая платформа, тем меньше преобразований выполняет SWC. --- ## Использование SWC с TypeScript Одним из наиболее популярных сценариев является тестирование TypeScript-кода. Исходный файл: ```ts export function sum(a: number, b: number): number { return a + b; } ``` После трансформации SWC удаляет типы: ```js export function sum(a, b) { return a + b; } ``` Важно понимать принцип работы. SWC: * удаляет типы; * компилирует синтаксис. SWC не выполняет: * проверку типов; * анализ корректности типизации. Поэтому проверка типов обычно выносится в отдельную команду: ```bash tsc --noEmit ``` Часто используются оба процесса: ```bash npm run test npm run typecheck ``` Такой подход обеспечивает одновременно высокую скорость и строгий контроль типов. --- ## React, JSX и TSX SWC обладает встроенной поддержкой React. Пример компонента: ```tsx export function Button() { return ; } ``` Конфигурация: ```json { "jsc": { "parser": { "syntax": "typescript", "tsx": true }, "transform": { "react": { "runtime": "automatic" } } } } ``` Параметр: ```json { "runtime": "automatic" } ``` включает современную JSX-трансформацию React без необходимости импортировать React вручную. --- ## Поддержка Decorators Во многих корпоративных проектах используются декораторы. Пример: ```ts class UserService { @Log() create() {} } ``` Настройка: ```json { "jsc": { "parser": { "syntax": "typescript", "decorators": true }, "transform": { "legacyDecorator": true, "decoratorMetadata": true } } } ``` Параметры: | Опция | Назначение | | ----------------- | ---------------------------- | | legacyDecorator | Поддержка legacy-декораторов | | decoratorMetadata | Генерация metadata | Такая конфигурация часто используется совместно с NestJS. --- ## Настройка через vite.config.ts Поскольку Vitest построен поверх Vite, большинство настроек задаётся через конфигурацию Vite. Пример: ```ts import { defineConfig } from "vite"; export default defineConfig({ test: { globals: true, environment: "node" } }); ``` Если в проекте используется плагин SWC, он также подключается здесь. --- ## Использование SWC в React-проектах на Vite Наиболее распространённый вариант: ```bash npm install -D @vitejs/plugin-react-swc ``` Конфигурация: ```ts import react from "@vitejs/plugin-react-swc"; import { defineConfig } from "vite"; export default defineConfig({ plugins: [react()] }); ``` Теперь: * React-компоненты компилируются через SWC; * Vitest использует ту же инфраструктуру преобразования; * сокращается время запуска тестов. --- ## Сравнение Babel и SWC в Vitest ### Babel Преимущества: * огромная экосистема; * множество плагинов; * зрелость решения. Недостатки: * более медленная компиляция; * значительное потребление памяти. --- ### SWC Преимущества: * высокая скорость; * низкое потребление ресурсов; * поддержка TypeScript и JSX из коробки. Недостатки: * меньше плагинов; * часть возможностей Babel может отсутствовать. --- ## Source Maps в тестах Source maps позволяют видеть реальные строки исходного файла при возникновении ошибок. Настройка: ```json { "sourceMaps": true } ``` Без source maps стек вызовов может выглядеть так: ```text dist/file.js:421 ``` Со включёнными картами: ```text src/services/user.ts:18 ``` Это значительно упрощает отладку. --- ## Трансформация модулей SWC способен преобразовывать различные форматы модулей. ESM: ```json { "module": { "type": "es6" } } ``` CommonJS: ```json { "module": { "type": "commonjs" } } ``` Для современных проектов на Vitest предпочтительным вариантом считается ESM. --- ## Использование алиасов Во многих проектах применяются абсолютные пути. Пример: ```ts import { UserService } from "@/services/UserService"; ``` Настройка производится через Vite: ```ts import path from "path"; export default { resolve: { alias: { "@": path.resolve(__dirname, "./src") } } }; ``` После этого SWC корректно обрабатывает импорты при запуске тестов. --- ## Производительность при запуске тестов При использовании SWC ускорение становится заметным в нескольких сценариях. ### Большое количество TypeScript-файлов Каждый файл требует удаления типов и преобразования синтаксиса. SWC выполняет это значительно быстрее стандартного компилятора TypeScript. --- ### React-проекты Компиляция JSX является одной из наиболее затратных операций. SWC оптимизирован специально для подобных задач. --- ### Монорепозитории В репозиториях с десятками пакетов количество файлов может достигать десятков тысяч. SWC позволяет заметно сократить: * холодный запуск; * повторные прогоны; * время работы CI. --- ## Ограничения SWC Несмотря на высокую производительность, существуют особенности, которые необходимо учитывать. ### Отсутствие проверки типов SWC не заменяет TypeScript Compiler. Ошибочный код: ```ts const age: number = "30"; ``` может быть успешно скомпилирован. Контроль типов должен выполняться отдельно. --- ### Ограниченная экосистема плагинов Babel существует значительно дольше. Поэтому некоторые редкие плагины могут не иметь аналогов в SWC. --- ### Различия в трансформациях В отдельных случаях результат работы Babel и SWC может отличаться. Особенно это касается: * экспериментальных возможностей языка; * нестандартных Babel-плагинов; * сложных цепочек трансформаций. Перед миграцией крупных проектов рекомендуется проверять совместимость тестового окружения. --- ## Практическая конфигурация для Vitest и React Файл `vite.config.ts`: ```ts import { defineConfig } from "vite"; import react from "@vitejs/plugin-react-swc"; export default defineConfig({ plugins: [react()], test: { globals: true, environment: "jsdom", setupFiles: "./src/setupTests.ts" } }); ``` Файл `.swcrc`: ```json { "jsc": { "target": "es2022", "parser": { "syntax": "typescript", "tsx": true, "decorators": true }, "transform": { "react": { "runtime": "automatic" } } }, "sourceMaps": true } ``` Такая конфигурация обеспечивает: * быструю компиляцию TypeScript; * поддержку React и TSX; * корректную обработку декораторов; * удобную отладку через source maps; * высокую скорость запуска тестов в Vitest. --- ## Рекомендации по использованию SWC в тестовой инфраструктуре Для большинства современных проектов оптимальной считается следующая схема: ```text TypeScript │ ▼ SWC │ ▼ Vitest │ ▼ Выполнение тестов ``` При этом проверка типов запускается отдельно: ```bash tsc --noEmit ``` Подобная архитектура позволяет объединить преимущества двух инструментов: * максимальную скорость компиляции благодаря SWC; * полноценную типовую безопасность благодаря TypeScript Compiler; * быстрый запуск тестов через Vitest; * эффективную работу в крупных кодовых базах и CI/CD-конвейерах.